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?

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)

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.


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.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.