Pretty Django model instaces updating

114 views
Skip to first unread message

Kee

unread,
Mar 1, 2012, 1:24:36 PM3/1/12
to Django developers
This helper could be used as an instance method in
django.core.models.Model class:
https://gist.github.com/1951748

Carl Meyer

unread,
Mar 1, 2012, 2:29:34 PM3/1/12
to django-d...@googlegroups.com
Hi Kee,

Thanks for the suggestion. I agree that that's a useful pattern and one
I frequently use myself. The problem is that the model instance
namespace is a precious resource, and using up any more of it than we
already do can easily lead to backwards-compatibility problems. In this
case, I don't think turning a one-liner into a shorter one-liner
justifies using up more of that namespace.

Carl

signature.asc

Meir Kriheli

unread,
Mar 1, 2012, 2:44:00 PM3/1/12
to django-d...@googlegroups.com
Hi,
IIRC, it won't call the instance's save() method nor fire model related signals,
which isn't the expected behaviour from an instance method.

Cheers
--

Anssi Kääriäinen

unread,
Mar 1, 2012, 2:45:48 PM3/1/12
to django-d...@googlegroups.com


On Thursday, March 1, 2012 9:29:34 PM UTC+2, Carl Meyer wrote:

Thanks for the suggestion. I agree that that's a useful pattern and one
I frequently use myself. The problem is that the model instance
namespace is a precious resource, and using up any more of it than we
already do can easily lead to backwards-compatibility problems. In this
case, I don't think turning a one-liner into a shorter one-liner
justifies using up more of that namespace.

Carl

I suggest implementing .save(only_fields=list_of_fields).

That should not be hard to implement and will not consume the namespace of models. Signals are fired properly. In addition, update() would be a bit strange instance method: it updates the specified fields by the kwargs (the instance's field values do not matter). In addition, after the update the instance's fields are not updated to reflect what was just saved.

 - Anssi

Kee

unread,
Mar 1, 2012, 4:48:32 PM3/1/12
to Django developers
Fully agree with Anssi Kääriäinen,

the best approach is ``only_fields`` for save()``

On Mar 1, 11:45 pm, Anssi Kääriäinen <anssi.kaariai...@thl.fi> wrote:
> On Thursday, March 1, 2012 9:29:34 PM UTC+2, Carl Meyer wrote:
>
> > <https://gist.github.com/1951748>

Tai Lee

unread,
Mar 1, 2012, 11:46:43 PM3/1/12
to Django developers
This is easy to achieve in your own code. Create your own BaseModel
class that all your models subclass. Instead of using
`.filter().update()`, do this:

def update(self, **kwargs):
"""
Updates the fields specified in `kwargs` and then call `save()`.
"""
if kwargs:
for k, v in kwargs.iteritems():
setattr(self, k, v)
self.save(force_update=True)

This will still fire the `save` signals, and your model instance will
have the new values as well as having them saved to the database.

I think it is also easier than assigning values to each field and then
calling `.save(only_fields[field1, field2])`, which I don't think is
any better than filter().update(). If `save(only_fields=...)` were to
only write specified fields to the database, this might cause
unexpected side effects with `save` signals?

If you don't like the name `update`, or it clashes with something else
in your model namespaces, just use something else.

I don't think this warrants inclusion in Django core.

Cheers.
Tai.

Carl Meyer

unread,
Mar 2, 2012, 12:28:30 AM3/2/12
to django-d...@googlegroups.com
On 03/01/2012 09:46 PM, Tai Lee wrote:
> This is easy to achieve in your own code. Create your own BaseModel
> class that all your models subclass. Instead of using
> `.filter().update()`, do this:
>
> def update(self, **kwargs):
> """
> Updates the fields specified in `kwargs` and then call `save()`.
> """
> if kwargs:
> for k, v in kwargs.iteritems():
> setattr(self, k, v)
> self.save(force_update=True)
>
> This will still fire the `save` signals, and your model instance will
> have the new values as well as having them saved to the database.
>
> I think it is also easier than assigning values to each field and then
> calling `.save(only_fields[field1, field2])`, which I don't think is
> any better than filter().update(). If `save(only_fields=...)` were to
> only write specified fields to the database, this might cause
> unexpected side effects with `save` signals?

The "only_fields" kwarg suggestion comes from ticket 4102, and it is
primarily intended as a performance optimization for large models by
only sending the values of certain fields to the database at all,
something that your proposed code does not do.

Carl

signature.asc

Anssi Kääriäinen

unread,
Mar 2, 2012, 12:33:13 AM3/2/12
to django-d...@googlegroups.com
I should have mentioned that ticket. This is one of the tickets where the feature isn't hard to implement. Getting the API exactly correct is hard. And keeping the feature restricted is even harder...

 - Anssi

Jeremy Dunck

unread,
Mar 2, 2012, 12:33:02 AM3/2/12
to django-d...@googlegroups.com
On Thu, Mar 1, 2012 at 9:28 PM, Carl Meyer <ca...@oddbird.net> wrote:
....

> The "only_fields" kwarg suggestion comes from ticket 4102, and it is
> primarily intended as a performance optimization for large models by
> only sending the values of certain fields to the database at all,
> something that your proposed code does not do.

It is also useful in the case where you have fields on the model which
have authoritatively changed, but have other local values which might
be stale.

Kee

unread,
Oct 9, 2012, 12:44:01 PM10/9/12
to django-d...@googlegroups.com
I also propose these two little helpers, one is ``refresh()`` and other is ``update()``
https://gist.github.com/3859962

``update()`` updates instance without calling ``save()`` and calling signals and returns updated instance (sometimes you want to update instance without involving save signals)

This helpers are particularly useful in writing tests, may be makes sense including them not to ``djanog.db.models`` but to ``django.test`` or ``django.test.tools``.

Reply all
Reply to author
Forward
0 new messages