I have the following view on my Django app and I need to update one object
status_id is a ForeignKey field and it has some default values loaded via fixtures
def stopObject(request, id_object):
object = Object.objects.get(id=id_object)
object.status_id = 1
object.save()
I’m getting the classical error where I need to assign the object, not its Id. There are countless questions on SO about this problem, but I came looking for an answer I didn’t found
I know very well I can just perform a fetch from the database and assign to status, but I want to explore other possibilities, even though they may not be the best practices
EDIT sharing the models:
class Status(models.Model):
id = models.AutoField(primary_key=True)
description = models.CharField(max_length=32, unique=True)
class Object(models.Model):
id = models.AutoField(primary_key=True)
status_id = models.ForeignKey(Status,
db_column="status_id",
default=3,
null=True,
blank=True,
related_name='objects',
on_delete=models.SET_NULL)
# other fields
>Solution :
status_idis aForeignKey.
Normally one does not add a suffix …_id to a ForeignKey field, since Django will automatically add a "twin" field with an …_id suffix. Therefore it should be status, instead of , so:status_id
class Object(models.Model):
status = models.ForeignKey(
Status,
default=3,
null=True,
blank=True,
related_name='objects',
on_delete=models.SET_NULL,
)
this then also prevents having to specify the db_column='status_id'.
If you thus rename the field to status, you can use status_id. If not, you can use:
# if the field is named status
def stopObject(request, id_object):
object = Object.objects.get(id=id_object)
object.status_id = 1
object.save()
If you decide to keep it status_id for some reason, we can use:
# if the field is remains status_id
def stopObject(request, id_object):
object = Object.objects.get(id=id_object)
object.status_id_id = 1
object.save()
You can boost performance further by just updating the Object instead of fetching and saving:
# if the field is remains status_id
def stopObject(request, id_object):
object = Object.objects.filter(id=id_object).update(status_id_id=1)
or with the renamed field:
# if the field is named status
def stopObject(request, id_object):
object = Object.objects.filter(id=id_object).update(status_id=1)
Note: Django will add by default an
AutoField[Django-doc] asprimary_key=Trueto a model with nameidif you do not specify a primary key yourself, so there is no need to explicitly declare a primary key.