formularios - modelos en django
¿Cómo actualizar múltiples campos de una instancia de modelo django? (5)
Actualizar usando la update()
Discussion.objects.filter(slug=d.slug)
.update(title=form_data[''title''],
category=get_object_or_404(Category, pk=form_data[''category'']),
description=form_data[''description''], closed=True)
Me pregunto, ¿cuál es una forma estándar de actualizar múltiples campos de una instancia de un modelo en django? ... Si tengo un modelo con algunos campos,
Class foomodel(models.Model):
field1 = models.CharField(max_length=10)
field2 = models.CharField(max_length=10)
field3 = models.CharField(max_length=10)
...
... y lo instauro con un campo dado, y luego, en un paso separado, quiero proporcionar el resto de los campos, ¿cómo hago eso solo pasando un diccionario o valores clave de params? ¿Posible?
En otras palabras, supongamos que tengo un diccionario con algunos datos que tienen todo lo que quiero escribir en una instancia de ese modelo. La instancia del modelo se ha instanciado en un paso separado y digamos que aún no se ha conservado. Puedo decir foo_instance.field1 = my_data_dict[''field1'']
para cada campo, pero algo me dice que debería haber una manera de llamar a un método en la instancia del modelo donde paso todos los pares de valores de campo a la vez y se actualiza ellos. Algo así como foo_instance.update(my_data_dict)
. No veo ningún método integrado como este, ¿me lo estoy perdiendo o cómo se hace de manera eficiente?
Tengo la sensación de que es una pregunta obvia de RTM, pero no la he visto en los documentos.
Es tentador meterse con __dict__
, pero eso no se aplicará a los atributos heredados de una clase principal.
Puede iterar sobre el dict para asignar al objeto:
for (key, value) in my_data_dict.items():
setattr(obj, key, value)
O puede modificarlo directamente desde un conjunto de consulta (asegurándose de que su conjunto de consultas solo devuelva el objeto que le interesa):
FooModel.objects.filter(whatever="anything").update(**my_data_dict)
Obtengo el nombre de la clave principal, la utilizo para filtrar con Queryset.filter()
y actualizo con Queryset.update()
.
fooinstance = ...
# Find primary key and make a dict for filter
pk_name foomodel._meta.pk.name
filtr = {pk_name: getattr(fooinstance, pk_name)}
# Create a dict attribute to update
updat = {''name'': ''foo'', ''lastname'': ''bar''}
# Apply
foomodel.objects.filter(**filtr).update(**updat)
Esto me permite actualizar una instancia sea cual sea la clave principal.
Parece algo tan natural que querrías hacer pero, como tú, tampoco lo he encontrado en los documentos. Los documentos dicen que debe sub-clase save () en el modelo. Y eso es lo que hago.
def save(self, **kwargs):
mfields = iter(self._meta.fields)
mods = [(f.attname, kwargs[f.attname]) for f in mfields if f.attname in kwargs]
for fname, fval in mods: setattr(self, fname, fval)
super(MyModel, self).save()
Puedes intentar esto:
obj.__dict__.update(my_data_dict)