Atualize apenas campos específicos em um models.Model

90

Eu tenho uma modelo

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

e agora quero atualizar apenas o activecampo. Então eu faço isso:

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

Agora recebo um erro IntegrityError: PRIMARY KEY must be unique.

Estou certo com este método de atualização?

Usuário Registrado
fonte

Respostas:

181

Para atualizar um subconjunto de campos, você pode usar update_fields:

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

O update_fieldsargumento foi adicionado no Django 1.5. Em versões anteriores, você poderia usar o update()método:

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

Normalmente, a maneira correta de atualizar certos campos em uma ou mais instâncias do modelo é usar o update()método no respectivo queryset. Então você faz algo assim:

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

Dessa forma, você não precisa mais chamar o save()seu modelo porque ele é salvo automaticamente. Além disso, o update()método retorna o número de instâncias de pesquisa que foram afetadas por sua atualização.

pemistahl
fonte
2
Obrigado. Tentei com em .getvez de .filtere não funcionou. Mas com filtro funciona bem. Você sabe o que há de errado com meu código acima?
Usuário registrado em
Seu problema pode estar relacionado a question_id. De onde vem esse valor? E qual linha exata aumenta o IntegrityError?
pemistahl
question_idvem de urls (?P<question_id>\d+). Minha falha foi que no servidor de trabalho o django 1.4 está instalado e meu código é 1.5. Mas com seu código está funcionando bem.
Usuário registrado em
2
@RegisteredUser, parece que não há método de "atualização" em objetos, apenas em querysets. Quando você usa .filter (), você obtém um queryset (contendo zero ou mais objetos) de volta. Quando você usa .get (), obtém um único objeto.
mgojohn
Por padrão, chamar save()(solução @Alasdair) é uma solução mais segura, porque esse método pode acionar coisas como validação ou qualquer código personalizado do update()que não.
David D.