On 08/06/12 16:16, Anssi Kääriäinen wrote:
> 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?

Precisely.

> 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.

Right. There are obviously limits to any approach, as (as I've seen
people do) you can generate models dynamically at runtime as the
application is loaded - that said, migrations are not going to be a
required feature, and so some limits on how you're allowed to arrange
your models seems sensible.

> 
> 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).

Yes, I'd say versioning is unnecessary, as you can just use a different
name - the new migrations stuff will also include a much easier way to
delete older migrations from the history and thus wipe out-of-date
references, while still keeping things the same in the database.

> 
> 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.

There's no way of doing a raw SQL method without extra code as Django
will never emit ALTER TABLE statements by itself (otherwise, we could
just capture it from the cursor during syncdb or something).

The new format will include provision for just having a big block of raw
SQL, though - so if someone wants to fall back to doing that it's pretty
easy.

Andrew

-- 
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