On Tue, May 14, 2013 at 7:38 AM, Shai Berger <s...@platonix.com> wrote:

> On Tuesday 14 May 2013, Alex Ogier wrote:
> >
> >  It's a totally new behavior that has
> > plenty of corner cases such as foreign keys, and especially
> OneToOneFields.
> >
> Another one is initializers: get() or any other method of fetching an
> object
> from the database will call __init__() with the fields as *args; this
> allows a
> model to manipulate these fields or calculate derived fields or whatever.
> refresh() may put such objects in an inconsistent state by default -- to
> prevent this, we would need a rule along the lines of "every model that
> overrides __init__() also needs to override refresh()".


There's also a systemic problem with any field that contains a python
reference. What happens when the value mutates in the database? Do you
create new instances of the value? What if it *didn't* mutate, how do you
know that?

Imagine a hypothetical python dict field, that serializes a Python dict to
JSON or a string or something and stores it in the database. What happens
in the following case?

a = A(dict_field={"hello": "world"})
d = a.dict_field
a.save()
a.refresh()
d["hello"] = "planet"    # does this mutate a.dict_field? does the answer
change if somebody changed the database in between saving and refreshing?

In the case of the OneToOneField, we need that the related Python instance
not be changed if the value didn't change, or else we will break the
one-to-one correspondence of the Python instances (two related one-to-one
models point back to our model). There doesn't really seem to be any way to
do that generally, so you probably have to create new instances every time
even when the value doesn't change except in this special case. Are
OneToOneFields special enough to warrant that? What about just your average
many-to-one relationship ("b = a.b_set[0]; a.refresh(); assert b not in
a.b_set")?

Basically, having a .refresh() necessitates having mutation semantics on
fields, where previously fields (not including deferred fields) were always
immutable. Either you are loading a new instance from the database, or you
are mutating a python value and re-serializing it to the database format.
You never have to reconcile python mutations with database mutations. Even
deferred fields have only one allowed mutation - from uninitialized to
initialized.

Best,
Alex Ogier

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to