django update - update logic of already set mandatory fields
I have a problem when I update an object. This is the model:
class HourRecord(models.Model):
day_of_work = models.PositiveIntegerField(max_length=1)
date_of_work = models.DateField(verbose_name='creation date')
who_worked = models.ForeignKey(User)
project = models.ForeignKey(Project, related_name='hour_record_set', null=True)
created_by = models.ForeignKey(User, editable=False, related_name='hour_record_creator')
created = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='creation date')
modified_by = models.ForeignKey(User, editable=False, related_name='hour_record_modifier')
modified = models.DateTimeField(auto_now=True, editable=False)
开发者_开发问答 def save(self, request):
if not self.id:
self.who_worked = request.user
self.created_by = request.user
self.modified_by = request.user
super(HourRecord, self).save()
The created_by field should only be set if its a new object. Therefore the "if not self.id:". This worked fine till now.
Till now I updated the object like this:
if hrform.is_valid():
hour_record = hrform.save(commit=False)
hour_record.save(request)
But when I update the model like this I get an error:
project = Project.objects.get(id=project_pk)
hr_object = HourRecord(id=hour_record_pk, day_of_work=weekday, date_of_work=date, who_worked=request.user, project=project)
hr_object.save(request)
The error message is:
Column 'created_by_id' cannot be null
Thats strange to me since the created_by column has been already set. I checked it in the database. After this error message when I check again the object is updated and created_by_id is set to null. Actually this is strange. I get an error message + the row is updated.
The second approach is called from within a json data handling view. But I don't think that it has anything to do with it. I think I can circumvent this problem when I reset the created_by_id, but that is not what I want to do, since it corrupts the logic of this created_by field.
Well, the issue appears to be that you are explicitly setting the id
field when you instantiate the HourRecord object:
hr_object = HourRecord(id=hour_record_pk,...
So when you get to the save()
method, it checks if it has an ID... and it does, so it doesn't set who_worked
and created_by
.
I wonder why you need to set the ID. Normally, you should let the database set it automatically via the autoincrement.
(Not related to your issue, but your save
method should accept the force_update
and force_insert
parameters, and pass them to the super method. The easiest way to do this is to get into the habit of always using *args, **kwargs
when overriding a method.)
Edit: To answer your question of why this doesn't work like an update statement, it's because you're explicitly replacing the old object with a new one. In effect, you're deleting the old db entry and inserting a completely new set of data. There'd be no way for Python to know whether you intended to keep a field's old value, or set it to NULL, for example.
The way to do this, as you have noted, is to get the existing object and updating its attributes explicitly.
精彩评论