我有模型
class Survey(models.Model):
created_by = models.ForeignKey(User)
question = models.CharField(max_length=150)
active = models.NullBooleanField()
def __unicode__(self):
return self.question
现在我只想更新
active
字段。所以我这样做:
survey = get_object_or_404(Survey, created_by=request.user, pk=question_id)
survey.active = True
survey.save(["active"])
现在我收到错误
IntegrityError: PRIMARY KEY must be unique
。
我这个更新方法对吗?
update_fields
:
survey.save(update_fields=["active"])
update_fields
参数是在 Django 1.5 中添加的。在早期版本中,您可以使用 update()
方法来代替:
Survey.objects.filter(pk=survey.pk).update(active=True)
通常,更新一个或多个模型实例中某些字段的正确方法是在相应的查询集上使用
update()
方法。然后你做这样的事情:
affected_surveys = Survey.objects.filter(
# restrict your queryset by whatever fits you
# ...
).update(active=True)
这样,您就不再需要在模型上调用
save()
,因为它会自动保存。此外,update()
方法还会返回受您的更新影响的调查实例的数量。
您可以使用此 mixin,它可用于检测模型实例中哪些字段已更改,并将该信息传递给 save 方法。这是 mixin 的描述:
通过在模型中使用此mixin,您可以方便地跟踪并仅保存已修改的字段,这有助于优化数据库更新并减少不必要的数据库查询。
from django.db import models
class UpdateFieldsMixin(models.Model):
""" Detects which field changed and passes it to save method """
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
fields = (field.name for field in self._meta.fields)
self.old_instance_data = {name: getattr(self, name, None)
for name in fields}
def save(self, update_fields=None, **kwargs):
if self.pk:
update_fields = update_fields or {
k for k, v in self.old_instance_data.items()
if getattr(self, k, None) != v}
return super().save(update_fields=update_fields, **kwargs)
class Meta:
abstract = True
像这样使用它:
class YourModel(UpdateFieldsMixin, models.Model):
# Any code
def save(**kwargs):
# Any code
return super().save(**kwargs)
仅此而已。如果您有自定义保存方法,请确保调用 UpdateFieldsMixin.save。我建议使用 super() 就像上面的例子一样。