I've been reading similar questions to mine but they didn't help me.
I'm getting this error while I try to submit my form:
Cannot assign "9": "Characterweapons.weaponid" must be a "Weapons" instance.
This "9" is the ID from the weapon I got from my form, so that's very good, but when I try to put it in my weaponid column in my table Characterweapons, it gives me the error.
models.py:
from __future__ import unicode_literals
from django.db import models
class Category(models.Model):
categoryid = models.AutoField(db_column='CategoryID', primary_key=True) # Field name made lowercase.
categoryname = models.CharField(db_column='CategoryName', max_length=50, blank=True, null=True) # Field name made lowercase.
class Meta:
managed = True
db_table = 'category'
def __str__(self):
return self.categoryname
class Characters(models.Model):
characterid = models.AutoField(db_column='CharacterID', primary_key=True) # Field name made lowercase.
name = models.CharField(db_column='Name', unique=True, max_length=255) # Field name made lowercase.
level = models.IntegerField(db_column='Level') # Field name made lowercase.
credits = models.IntegerField(db_column='Credits') # Field name made lowercase.
class Meta:
managed = True
db_table = 'characters'
def __str__(self):
return '%s %s %s' % (self.name, self.level, self.credits)
class Weapons(models.Model):
weaponid = models.AutoField(db_column='WeaponID', primary_key=True) # Field name made lowercase.
weaponname = models.CharField(db_column='WeaponName', unique=True, max_length=255) # Field name made lowercase.
class Meta:
managed = True
db_table = 'weapons'
def __str__(self):
return '%s %r' % (self.weaponname, self.weaponid)
class Characterweapons(models.Model):
characterid = models.ForeignKey(Characters, models.DO_NOTHING, db_column='CharacterID') # Field name made lowercase.
weaponid = models.ForeignKey(Weapons, models.DO_NOTHING, db_column='WeaponID', blank=True, null=True) # Field name made lowercase.
categoryid = models.ForeignKey(Category, models.DO_NOTHING, db_column='CategoryID', blank=True, null=True) # Field name made lowercase.
quantity = models.IntegerField(db_column='Quantity', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = True
db_table = 'characterweapons'
def __str__(self):
return '%s' % (self.quantity)
class DjangoMigrations(models.Model):
app = models.CharField(max_length=255)
name = models.CharField(max_length=255)
applied = models.DateTimeField()
class Meta:
managed = True
db_table = 'django_migrations'
I don't know if it is a FK problem, PK... no idea and I cannot find information to solve it...
views.py: (where the error has to be):
def submission(request):
print("Registered successfully")
Name = request.POST["Name"]
Level = request.POST["Level"]
Credits = request.POST["Credits"]
Mainhand = request.POST["Mainhand"]
Offhand = request.POST["Offhand"]
info = Characters(name=Name,level=Level,credits=Credits)
info.save()
mh=
infomh = Weapons.objects.values_list('weaponid',flat=True)
a=0;
for a in infomh:
if a == Mainhand:
a = Mainhand;
print("a: ")
print(a)
print("Mainhand")
print(Mainhand)
print("infmh:")
print(infomh)
charid = Characters.objects.latest('characterid')
info_mh = Characterweapons(characterid=charid,categoryid=1,weaponid=a)
info_mh.save()
#info_oh = Characterweapons(characterid=charid,weaponid=9,categoryid=2)
#info_oh.save()
return return_charnames(request)
With these prints I made sure that the values of my weaponsID are correct, they are.
I also wanna point out that the value=9 in the column "weaponid" exists in "Weapons" table.
Thanks all.
I think you better first fix your models. In Django a ForeignKey is conceptually a reference to an object to which you refer, not the id. Of course in the database it is stored as an id, but that is a layer that you should not care much about.
So I would advice to first rename the fields like weaponid to weapon:
class Characterweapons(models.Model):
character = models.ForeignKey(Characters, models.DO_NOTHING, db_column='CharacterID')
weapon = models.ForeignKey(Weapons, models.DO_NOTHING, db_column='WeaponID', blank=True, null=True)
category = models.ForeignKey(Category, models.DO_NOTHING, db_column='CategoryID', blank=True, null=True)
quantity = models.IntegerField(db_column='Quantity', blank=True, null=True)
# ...
Now if you construct a ForeignKey with the name fieldname, Django actually introduces two fields: the fieldname which is - like said before - a reference to a model object to which the ForeignKey refers, and a field fieldname_id that stores the id (the primary key) of that object. These two fields thus act like "twins".
We can then rewrite the submission view like:
def submission(request):
print("Registered successfully")
name = request.POST["Name"]
level = request.POST["Level"]
credits = request.POST["Credits"]
mainhand = request.POST["Mainhand"]
offhand = request.POST["Offhand"]
info = Characters.objects.create(name=name, level=level,credits=credits)
if Weapons.objects.filter(weapon_id=mainhand).exists():
a = mainhand
info_mh = Characterweapons.objects.create(
character_id=info.pk,
category_id=1,
weapon_id=a
)
return return_charnames(request)
In the above I did some refactorings as well:
In Python variables in functions typically have lowercase names;
you do not need to loop over weapon_ids, you can use an EXISTS query, which is typically faster;
Instead of first constructing a model instance, and then obj.save() it, you can use Model.objects.create(..) instead;
you probably do not want to fetch the latest(..) value, but use the pk of the info object instead, since that is the one we constructed, and furthermore if there is no order defined (like here), the order can be any order the database likes, not per se the latest one added.
You probably still need to rewrite hardcoded identifiers (like a=1, and category_id=1, since it is perfectly possible that those objects do not exist in the database).
Your foreignkey weaponid in the model Characterweapons is a Weapon instance not only its id.
From that id, query the object and assign it.
Related
I'm creating a page that lets only admin add some assets. Each asset has a type. I have used a dropdown to select the asset_type. The selected value of asset_type gets passed into views.py but I can't get it written into the newly created asset object.
Here is my models.py
class assetType(models.Model):
title = models.CharField(max_length=150)
#property
def get_type(self):
return asset.objects.filter(asset_type=self.id)
def __str__(self):
return f"{self.title}"
class Meta:
verbose_name_plural = 'Asset Types'
class asset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, null=False)
asset_type = models.ForeignKey('assetType', on_delete=models.CASCADE, null=True)
asset_name = models.CharField(max_length=30, null=True) #unique=True
location = models.CharField(max_length=30, null=True)
brand = models.CharField(max_length=30, null=True)
purchase_year = models.PositiveIntegerField(blank=True, null=True)
isActive = models.BooleanField(default=True, null=True)
currentOwner = models.ForeignKey(User, default='', null=True, on_delete=models.CASCADE)
Here is createAssetView from views.py
#user_passes_test(lambda u: u.is_superuser)
def createAssetView(request):
assetTypeList = assetType.objects.all() # use assetType.title
assettype = request.POST.get('asset-type')
assetname = request.POST.get('asset-name')
locationn = request.POST.get('location')
brandd = request.POST.get('brand')
purchaseyear = request.POST.get('purchase-year')
isActivve = request.POST.get('is-active','') == 'on'
cuser=request.user
context={
"cuser":request.user,
"asset_type_list":assetTypeList,
"asset_type":assettype,
"asset_name":assetname,
"location":locationn,
"brand":brandd,
"purchase_year":purchaseyear,
"isActive":isActivve,
'iterator':range(2014,2050)
}
if request.method == 'POST':
new_asset = asset()
new_asset.asset_type_title=request.POST.get('asset-type')
new_asset.asset_name=assetname
new_asset.location=locationn
new_asset.brand=brandd
new_asset.purchase_year=purchaseyear
new_asset.isActive=True if isActivve else False
new_asset.currentOwner=cuser
print(assettype) # PRINT assettype
new_asset.save()
return redirect('createAssets')
return render(request, 'assets/createAsset.html', context)
The PRINT assettype statement prints selected asset type from the form, so the value is getting passed to the view, how should I populate the table with it?
Any suggestions or help will be highly appreciated. Thanks!
new_asset.asset_type_title=request.POST.get('asset-type')
This is the line where your problem is. You can't assign a foreign object like that, it does not automatically search for a match in another model.
You need to either provide the object to be used as a foreign key, or the object's primary key.
So we find our database entry for the selected type:
target_type = assetType.objects.get(title=assettype)
# this assumes you use unique titles for each assetType, see below
and then provide the new asset either with the object itself:
new_asset.asset_type = target_type
or its primary key:
new_asset.asset_type_id = target_type.pk
I strongly reccomend spending more time with django's documentation to strengthen your understanding of how foreign object relation is implemented in django. At least review the tutorials that focus on that.
Also consider the following:
The title field of the assetType model is not limited to be unique. What happens if two assetTypes with the same title are created?
Repetition of request.POST.get('asset-type')
I am new to django. What I am currently trying to do is set a value which is a primary key and non-editable automatically generated depending upon the values entered in the same model to some other fields. Here is an example:
class Student(models.Model):
student_id = models.CharField(max_length=100, primary_key=true)
name = models.CharField(max_length=100)
class = models.CharField(max_length=200)
roll_no = models.CharField(max_length=500)
So, what I am trying to achieve is if someone enters following information :
name = Haris
class = 8th
roll_no = 104011
The automatically generated primary key that would be non-editable for field "student_id" would be:
student_id = Haris_8th_104011
Does anyone have an idea how to achieve this? Hope my example made the query clear though.
You can do this way overriding save method. Note that class variable clashesh with original builtin class name please migrate once as i changed the variable name
class Student(models.Model):
student_id = models.CharField(max_length=100, primary_key=True, editable=False)
name = models.CharField(max_length=100)
classes = models.CharField(max_length=200)
roll_no = models.CharField(max_length=500)
def save(self, *args, **kwargs):
self.student_id = f'{self.name}_{self.classes}_{self.roll_no}'
super(Student,self).save(*args, **kwargs)
models.py
i have create foreignkey in table paymentsDetails i have stripe payment method which is working when user login session is created and by using session value i get the primarykey of that user by using 'ORM' method and then assign this primary key of specific user into the paymentdetails models field named as user_account_id
but i am getting error that i cannot assign 1 to PaymentsDetail.User_account_id must be a instance of UserAccountModel
class UserAccountModel(models.Model):
ContactEmail = models.EmailField(max_length=30)
FirstName = models.CharField(max_length=30)
LastName = models.CharField(max_length=40)
Counrty = models.CharField(max_length=50)
Phone = models.IntegerField()
ChooseUserName = models.CharField(max_length=30)
password = models.CharField(max_length=32)
EnterCaptcha = models.CharField(max_length=4)
payments = models.BooleanField(max_length=6, default=False)
showsponsor = models.CharField(max_length=30, default=False)
RegisteredDate = models.DateTimeField(auto_now_add=True, blank=True)
ActivationOn = models.DateField(auto_now_add=False,blank=True)
expiry_date = models.DateField(auto_now_add=False,blank=True)
def __str__(self):
return self.FirstName + ":" + self.ChooseUserName
class PaymentsDetail(models.Model):
refrer_name = models.CharField(max_length=32,default="", editable=False)
sponser_name = models.CharField(max_length=32)
status = models.CharField(default='comped', max_length=32)
s_id = models.CharField(max_length=32)
registered = models.DateTimeField(auto_now_add=True)
activated_date = models.DateField(auto_now_add=False)
Due_Date = models.DateField(auto_now_add=False)
payment = models.CharField(default='$',max_length=32)
User_Account_id = models.ForeignKey(UserAccountModel, on_delete=models.CASCADE, default=True, editable=True)
addprogrameReference = models.ForeignKey(AddProgramModel, on_delete=models.CASCADE, default=True, editable=True)
class Meta:
ordering = ['User_Account_id', 'addprogrameReference']
def str(self):
return self.refrer_name + ":" + self.user_account
i am getting the error
cannot assign 1 to PaymentsDetail.User_account_id must be a instance
of UserAccountModel
views.py
print("user payment"+str(charge.amount))
pays = str(charge.amount)
user_id = random.randint(0, 999) # returns a random integer
user = User.objects.get(username=str(rerredby))
userKey = user.pk
print("this one is for user upper")
# saving record
payment_insertion = PaymentsDetail.objects.create(
User_Account_id=userKey,
refrer_name=rerredby,
sponser_name=rerredby,
s_id=str(user_id),
registered=datetime.now(),
activated_date=datetime.now(),
Due_Date=datetime.now(),
payment=str(pays + "$"),
)
payment_insertion.save()
Simply change this string:
payment_insertion = PaymentsDetail.objects.create(
User_Account_id=user,
...)
You are trying to assign int object where Django expects an instance.
Your view implementation is not right. The model class expects the field User_Account_id to be an instance of of UserAccountModel (since, your model definition User_Account_id = models.ForeignKey(UserAccountModel, on_delete=models.CASCADE, default=True, editable=True) told it to expect it regardless of the your field name ending with an id). therefore, retrieve the UserAccountModel instance from db first.
However, if you still want to pass the id to instead of an object change the following in your view.
User_Account_id_id=userKey
ForeingKey fields can be populated by id instead of the concerned model object. But you have to append _id at the end of the field name e.g.
#models.py
class Author(models.Model):
name = models.CharField(max_length=250)
class Book(models.Model):
name = models.CharField(max_length=250)
author = models.ForeignKeyField(Author, on_delete=models.CASCADE)
# views.py
def create_book(request):
name = request.POST.get('name', '')
author_id = request.POST.get('author_id', '')
Book.objects.create(name=name, author_id=author_id)
return HttpResponse(status=201)
Notice that there is no author_id field defined in the Book model. This field is implicitly defined by django ORM once you defined author field as a ForeignKey reference to Author model.
Error - django.db.migrations.exceptions.CircularDependencyError: accounts.0001_initial, songs.0001_initial
I have two apps accounts and songs. Songs have two model files - models.py and song_metadata_models.py
accounts/models.py
class AppUser(models.Model):
user = models.OneToOneField(User)
user_languages = models.ManyToManyField('songs.SongLang')
user_genres = models.ManyToManyField('songs.SongGenre')
def __str__(self):
return self.user.username
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
songs/song_metadata_models.py
class SongGenre(models.Model):
short_name = models.CharField(max_length=10)
full_name = models.CharField(max_length=100)
def __str__(self):
return self.full_name
class SongLang(models.Model):
short_name = models.CharField(max_length=10)
full_name = models.CharField(max_length=100)
def __str__(self):
return self.full_name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
songs/models.py
class Song(models.Model):
# Fields
name = CharField(max_length=255)
slug = AutoSlugField(populate_from='name', blank=True)
created = DateTimeField(auto_now_add=True, editable=False)
last_updated = DateTimeField(auto_now=True, editable=False)
url = CharField(max_length=100)
artist = CharField(max_length=50)
album = CharField(max_length=50)
like = BooleanField(default=False)
dislike = BooleanField(default=False)
# Relationship Fields
requested_by = ForeignKey('accounts.AppUser', related_name='song_requested_by')
dedicated_to = ManyToManyField('accounts.AppUser', null = True, blank = True,related_name='song_dedicated_to')
recommended_to = ManyToManyField('accounts.AppUser', null = True, blank = True,related_name='song_recommended_to')
How to solve this? There is no circular dependency at models level then why this issue?
Solution 1: move the AppUser's many2many to SongLang and SongGenre. A m2m relationship is by default symetric so you can declare it on either side of the relationship (nb: just make sure to set the related_name to how your fields was named in the AppUser model).
Solution 2: move your SongGenre and SongLang models to a third app (the canonical solution to circular dependencies)
Solution 3: eventually try to first create the AppUser model without the m2m fields, creates the initial migration, then add the m2m fields (not sure it will work though).
I am trying to get a queryset but it is not displaying anything. Basically, I want to get the Asset objects that are assigned via foreign key to an employee, which is a foreign key of the signed in user.
views.py
def get_queryset(self):
assetlist = Asset.objects.filter(organisation__employee__user=self.request.user)
print(assetlist)
return assetlist
models.py
class Employee(models.Model):
name = models.CharField("Employee Name", max_length=50, blank=False)
email = models.CharField("Employee Email", max_length=50, blank=True)
user = models.ForeignKey(User)
clientID = models.ForeignKey(Organisation)
def save(self):
self.name = self.user.get_full_name()
self.email = self.user.email
super(Employee, self).save()
def __str__(self):
return self.name
class Asset(models.Model):
name = models.CharField("Asset Name", max_length=30, primary_key=True)
organisation = models.ForeignKey(Organisation)
def __str__(self):
return self.name
class Organisation(models.Model):
name = models.CharField("Organisation Name", max_length=50, blank=False)
location = models.TextField("Organisation Address", max_length=200, blank=True)
tel = models.CharField("Telephone Number", max_length=20)
def __str__(self):
return self.name
There is no employee field inside organisation. It's an reversed relation, there are many employees attached so you can't query it like that.
But there is something called related_name in django foreign keys, with use of that, your query should look like that:
assetlist = Asset.objects.filter(organisation__employee_set__user=self.request.user)
or if you specify your own related_name into employee -> organisation relation:
clientID = models.ForeignKey(Organisation, related_name="employees")
it will look like this:
assetlist = Asset.objects.filter(organisation__employees__user=self.request.user)
The answer was to approach from another model, as seen below:
assetlist = Sensor.objects.filter(asset__organisation__employee__user=self.request.user)
You have written wrong code. You want an Asset object by using:
assetlist = Asset.objects.filter(organisation__employee__user=self.request.user)
But you clearly can see in your models.py that there is no relationship between Organisation and Employee, then how can you get a result using organisation__employee...?
You should first create a ForeignKey field to relate with Employee model then your code will work fine.