Proposal: update_fields shortcut

101 views
Skip to first unread message

Paulo Poiati

unread,
Mar 5, 2014, 9:05:22 AM3/5/14
to Django Developers
Hello everyone,

While developing standard web applications one thing I frequently do is updating just one field of a model instance and save it after that. The best way to do that today (if you want to avoid the update in all the fields) is with the code bellow.

product.name = 'Name changed again'
product.save(update_fields=['name'])

I want to propose a shortcut for this kind of operation. I came up with two solutions.

Solution One

product.save(update_fields={'name': 'Name changed again'})

Solution Two (My preferred)

product.update_fields(name='Name changed again')

What do you guys think about this? 

[]’s
Paulo Poiati

Tom Evans

unread,
Mar 5, 2014, 11:06:53 AM3/5/14
to django-d...@googlegroups.com
On Wed, Mar 5, 2014 at 2:05 PM, Paulo Poiati <paulog...@gmail.com> wrote:
> Hello everyone,
>
> While developing standard web applications one thing I frequently do is
> updating just one field of a model instance and save it after that. The best
> way to do that today (if you want to avoid the update in all the fields) is
> with the code bellow.
>
> product.name = 'Name changed again'
> product.save(update_fields=['name'])
>
>
> I want to propose a shortcut for this kind of operation. I came up with two
> solutions.
>
> Solution One
>
> product.save(update_fields={'name': 'Name changed again'})
>
>
> Solution Two (My preferred)
>
> product.update_fields(name='Name changed again')
>
>

Solution Three (existing)

Product.objects.filter(pk=product.pk).update(name='Name changed again')

?

Cheers

Tom

Paulo Poiati

unread,
Mar 5, 2014, 12:06:11 PM3/5/14
to Django Developers
The solution three is also a really nice feature Tom, but it’s a different think, IMO. The update() is a QuerySet method and it does not call the save() method or trigger any of the signals. This is very important, specially for third party packages support. The django-model-utils for example

...
from model_utils.fields import MonitorField


class Invoice(model.Model):
   ...
   paid_at = MonitorField(monitor='paid')

   def pay(self):
      self.update_fields(paid=True)

[]’s
Paulo Poiati

Russell Keith-Magee

unread,
Mar 5, 2014, 7:18:19 PM3/5/14
to Django Developers
Sorry - can't say I'm a fan of either. 

If I had to pick one, I'd pick solution 1; solution 2 strikes me as introducing a second way to save models, which the Zen of Python counsels against. However, this at the "would you rather be shot in the knee or shot in the ankle" level of support. The only problem I see with your original "problem" syntax is that there is the potential to set an attribute and then forget it in the update_fields list; however, the price you pay for this is converting save() from a simple "commit" operation into a "modify and commit" operation.

Yours,
Russ Magee %-)

Paulo Poiati

unread,
Mar 5, 2014, 8:21:21 PM3/5/14
to django-d...@googlegroups.com
Thanks for your feedback Russel.

I understand and agree with your points, every solution has a drawback. I just think that the Zen of Python “There should be one-- and preferably only one --obvious way to do it.” shouldn’t be taken so seriously. 

What I mean is, isn’t QuerySet#get just a shortcut for a use case of QuerySet#filter? Isn’t QuerySet#first() just sugar to QuerySet[0]? What about the django.shortcuts module?

Don’t get me wrong, I enjoy the python philosophy, but I think it’s more a guideline than a law. 

[]’s
Paulo Poiati
Reply all
Reply to author
Forward
0 new messages