django update - 更新已设置的必填字段的逻辑

时间:2010-01-21 11:42:53

标签: django django-models

更新对象时出现问题。这是模型:

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()

只有在创建新对象时才应设置created_by字段。因此“if not self.id:”。到目前为止一切正常。

直到现在我更新了这样的对象:

if hrform.is_valid():
            hour_record = hrform.save(commit=False)
            hour_record.save(request)

但是当我像这样更新模型时,我收到一个错误:

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)

错误消息是:

Column 'created_by_id' cannot be null

这对我来说很奇怪,因为created_by列已经设置好了。我在数据库中检查了它。在我再次检查此错误消息后,更新对象并将created_by_id设置为null。其实这很奇怪。我收到一条错误消息+行已更新。

从json数据处理视图中调用第二种方法。但我不认为它与它有任何关系。我想我可以在重置created_by_id时绕过这个问题,但这不是我想要做的,因为它破坏了这个created_by字段的逻辑。

1 个答案:

答案 0 :(得分:1)

好吧,问题似乎是您在实例化HourRecord对象时明确设置了id字段:

hr_object = HourRecord(id=hour_record_pk,...

因此,当您使用save()方法时,它会检查它是否有ID ...而且确实如此,因此它不会设置who_workedcreated_by

我想知道你为什么需要设置ID。通常,您应该让数据库通过自动增量自动设置它。

(与您的问题无关,但您的save方法应该接受force_updateforce_insert参数,并将它们传递给super方法。最简单的方法是养成在重写方法时始终使用*args, **kwargs的习惯。)

编辑:要回答您为什么不能像更新语句那样工作的问题,这是因为您明确地用新对象替换旧对象。实际上,您将删除旧的db条目并插入一组全新的数据。例如,Python无法知道您是否打算保留字段的旧值,或将其设置为NULL。

正如您所指出的,执行此操作的方法是获取现有对象并明确更新其属性。