ChatGPT解决这个技术问题 Extra ChatGPT

Update only specific fields in a models.Model

I have a model

class Survey(models.Model):
    created_by = models.ForeignKey(User)
    question = models.CharField(max_length=150)
    active = models.NullBooleanField()
    def __unicode__(self):
        return self.question

and now I want to update only the active field. So I do this:

survey = get_object_or_404(Survey, created_by=request.user, pk=question_id)
survey.active = True
survey.save(["active"]) 

Now I get an error IntegrityError: PRIMARY KEY must be unique.

Am I right with this method to update?


A
Alasdair

To update a subset of fields, you can use update_fields:

survey.save(update_fields=["active"]) 

The update_fields argument was added in Django 1.5. In earlier versions, you could use the update() method instead:

Survey.objects.filter(pk=survey.pk).update(active=True)

While this answer makes .update() sound deprecated, both update methods are still available and non-deprecated as of Django 4.0. Great answer for mentioning both options, though :-)
p
pemistahl

Usually, the correct way of updating certain fields in one or more model instances is to use the update() method on the respective queryset. Then you do something like this:

affected_surveys = Survey.objects.filter(
    # restrict your queryset by whatever fits you
    # ...
    ).update(active=True)

This way, you don't need to call save() on your model anymore because it gets saved automatically. Also, the update() method returns the number of survey instances that were affected by your update.


Thanks. I tried it with .get instead of .filter and this doesn't work. But with filter it works nice. Do you know what is wrong with my code above?
Your problem might be related to question_id. Where does this value come from? And which exact line does raise the IntegrityError?
question_id comes from urls (?P<question_id>\d+). My fault was that on the working server django 1.4 is installed and my code is 1.5. But with your code it's working fine.
@RegisteredUser, looks like there's no "update" method on objects, just on querysets. When you use .filter(), you get a queryset (holding zero or more objects) back. When you use .get() you get a single object.
By default, calling save() (@Alasdair solution) is a safer solution, because this method may triggers things like validation, or any custom code, than update() does not.