n 8 kesä, 00:20, Andrew Godwin <and...@aeracode.org> wrote:
> On 07/06/12 21:56, Anssi K ri inen wrote:
>
> > Is the reason for this to be able to track changes to field by
> > checking if its init arguments have changed? Why is it not possible to
> > track changes by checking the SQL output the field will generate
> > instead? This is guaranteed to be a string, and should be readily
> > available for any field. I am just trying to get up to speed here...
>
> No, it is so a model can be instantiated for any point in time
> (essentially a versioned ORM). This is needed so that any custom
> python/ORM code in migrations see the models as they were when they were
> created, and thus won't get weirded out by the columns not matching.
>
> There was a decent explanation about why and how models are resurrected
> like this on south-users ages ago, but I think that post may have been
> lost to the voids of time.

I did a little digging into South code, and I think I now understand
the needs. Basically, when you migrate a model, you might need to read
the database data by using the old model definitions. You can't use
the currently installed model definition because it does not match the
database state. So, you read in by using the unfreezed old model
definition, do needed changes to data, do actual schema migrations,
then continue to next freezed state, do changes to data, migrate
schema and so on. Even if you don't need the ORM for data migrations,
you might need the old field definition: how to generate a column's
SQL for a field in multidb friendly way if you don't have the field
available?

The problem with the above approach is that if for example a field
__init__ definition is changed (or the user deletes unneeded field
code) there goes your ability to do migrations. The migrations do not
contain all the needed data to do the migrations. You should have the
fields available for your whole migration history, and the fields
should not change in ways that break the unfreeze. This is also the
reason why identifying fields uniquely is so important - to unfreeze,
you need the original field class. If you can't get the original field
definition back, your migration is nearly worthless.

The dependency on having the field code available is by design. This
is somewhat fragile no matter what you do, because you might need
historical code to be able to run your migrations. But, it seems there
is no way around this if you want to have multidb capabilities for
custom fields, or any kind of versioned ORM capability available.

I favor the explicit registrations API with free format strings. The
idea would be that the field author will do:
    migrations.register('mypackage:somefield', SomeField)
If he needs to later do incompatible changes to the field, he could
change the registration to
    migrations.register('mypackage:somefield:v2', SomeField)
Likely field versioning isn't commonly needed. At some point old
migrations lose their value, and incompatible changes in fields aren't
that common to begin with. Still, if the registration string is just a
string, then the ability to have the ':v2' in there comes for free.
For example, Django's XMLField could be resurrected for migrations by
downloading its code, and registering it to 'django:xmlfield' (or
whatever the key was previously).

The __init__ args and kwargs needed for unfreeze should be asked
directly from the Field, just as Andrew suggested in his original
mail. If a field is registered to migrations, then it will need to
provide "get init arguments" method.

I think I am finally up to speed with this discussion... In short: +1
for field registering, -0 for automatic fields.py introspection, +1
for "get init arguments".

To me it seems there would be room for different kind of migrations,
too. For example, just record the raw SQL needed. This is the method I
am using (manually) currently. This is totally multidb unfriendly, but
it doesn't matter for some use cases. It seems South migrations files
could be used in this way, too, but there isn't support for recording
raw SQL changesets between current database state, and current
models.py.

 - Anssi

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

Reply via email to