[Django]-How do I use a dictionary to update fields in Django models?

128👍

✅

Here’s an example of create using your dictionary d:

Book.objects.create(**d)

To update an existing model, you will need to use the QuerySet filter method. Assuming you know the pk of the Book you want to update:

Book.objects.filter(pk=pk).update(**d)

93👍

Use ** for creating a new model. Loop through the dictionary and use setattr() in order to update an existing model.

From Tom Christie’s Django Rest Framework

https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/serializers.py

for attr, value in validated_data.items():
    setattr(instance, attr, value)
instance.save()

77👍

If you know you would like to create it:

Book.objects.create(**d)

Assuming you need to check for an existing instance, you can find it with get or create:

instance, created = Book.objects.get_or_create(slug=slug, defaults=d)
if not created:
    for attr, value in d.items(): 
        setattr(instance, attr, value)
    instance.save()

As mentioned in another answer, you can also use the update function on the queryset manager, but i believe that will not send any signals out (which may not matter to you if you aren’t using them). However, you probably shouldn’t use it to alter a single object:

Book.objects.filter(id=id).update()

11👍

if you have already Django object and you want to update it’s field, you may do it without filter. because you have it already, in this case, yoy may :

your_obj.__dict__.update(your_dict)
your_obj.save()

1👍

Adding on top of other answers, here’s a bit more secure version to prevent messing up with related fields:

def is_simple_editable_field(field):
    return (
            field.editable
            and not field.primary_key
            and not isinstance(field, (ForeignObjectRel, RelatedField))
    )

def update_from_dict(instance, attrs, commit):
    allowed_field_names = {
        f.name for f in instance._meta.get_fields()
        if is_simple_editable_field(f)
    }

    for attr, val in attrs.items():
        if attr in allowed_field_names:
            setattr(instance, attr, val)

    if commit:
        instance.save()

It checks, that field you’re trying to update is editable, is not primary key and is not one of related fields.

Example usage:

book = Book.objects.first()
update_from_dict(book, {"num_pages":40, author:"Jack", date:"3324"})

The luxury DRF serializers .create and .update methods have is that there is limited and validated set of fields, which is not the case for manual update.

1👍

To update one record you can use very handy function:

class Book(models.Model):
    num_pages = ...
    author = ...
    date = ...

    def update(self,*args, **kwargs):
            for name,values in kwargs.items():
                try:
                    setattr(self,name,values)
                except KeyError:
                    pass
            self.save()

and then:

d = {"num_pages":40, author:"Jack", date:"3324"}
book = Book.objects.first()
book.update(**d)

Leave a comment