Actualice solo campos específicos en un modelo.

92

Tengo un 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

y ahora quiero actualizar solo el activecampo. Entonces hago esto:

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

Ahora me sale un error IntegrityError: PRIMARY KEY must be unique.

¿Estoy en lo cierto con este método para actualizar?

usuario registrado
fuente

Respuestas:

187

Para actualizar un subconjunto de campos, puede usar update_fields:

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

El update_fieldsargumento se agregó en Django 1.5. En versiones anteriores, podría usar el update()método en su lugar:

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

Por lo general, la forma correcta de actualizar ciertos campos en una o más instancias del modelo es usar el update()método en el conjunto de consultas respectivo. Entonces haces algo como esto:

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

De esta manera, ya no necesita llamar save()a su modelo porque se guarda automáticamente. Además, el update()método devuelve el número de instancias de encuestas que se vieron afectadas por su actualización.

pemistahl
fuente
2
Gracias. Lo probé con en .getlugar de .filtery esto no funciona. Pero con el filtro funciona bien. ¿Sabes qué está mal con mi código anterior?
Usuario registrado
Su problema puede estar relacionado con question_id. ¿De dónde proviene este valor? ¿Y qué línea exacta eleva el IntegrityError?
pemistahl
question_idproviene de urls (?P<question_id>\d+). Mi culpa fue que en el servidor de trabajo django 1.4 está instalado y mi código es 1.5. Pero con tu código está funcionando bien.
Usuario registrado
2
@RegisteredUser, parece que no hay un método de "actualización" en los objetos, solo en los conjuntos de consultas. Cuando usa .filter (), obtiene un conjunto de consultas (que contiene cero o más objetos). Cuando usa .get () obtiene un solo objeto.
mgojohn
De forma predeterminada, llamar a save()(solución @Alasdair) es una solución más segura, porque este método puede desencadenar cosas como la validación o cualquier código personalizado que update()no.
David D.