Hi Carsten,

On Thursday, July 16, 2015 at 12:44:55 PM UTC-6, Carsten Fuchs wrote:
>
> Am 2015-07-16 um 18:15 schrieb Gergely Polonkai: 
> > 1) create the "through" model, add it to the migration file 
> > 2) migrate all m2m instances (e.g. iterate over all Bereich objects then 
> > iterate through its users, creating a UserBereichAssignment object for 
> > each (all this done in a migrations.RunPython call) 
>
> Ok. I've never used migrations.RunPython before, but I'm quite confident 
> that I can manage it. 
>

You could also use RunSQL instead of RunPython for this data migration step 
- personally I often find that easier (and almost always more efficient) 
for a simple data migration, since all you need is a SQL query to copy some 
data from one table to another, you don't need any Python conveniences or 
model instances along the way.

But either can work, it really just depends how comfortable you are with 
raw SQL.
 

> Would the migration for step 2) be a separate migration file from step 
> 1), or is the migration file of step 1) edited to cover step 2) as well? 
>

Separate migration. In general you can't put schema alterations and data 
migrations in the same migration file, because then they'll try to run in 
the same transaction, and PostgreSQL at least doesn't like that.

In general, for complex changes, this three-step dance (one migration to 
add the new field/table, a second migration to copy the data, and a third 
migration to remove the old field/table) is very common and the right way 
to do things.
 

> > 3) change the m2m field by adding the through option, and add this 
> > change to the migrations file. 
>
> Same question: Is this supposed to go into a separate migration file or 
> into the common migrations file from above? 
>
> And won't this last step trigger the same error as before? ("... you 
> cannot alter to or from M2M fields, or add or remove through= on M2M 
> fields") ? 
>

This part I'm not sure about without trying it. I'm honestly not sure what 
exactly Gergely was recommending. Based on my reading of the code, the 
error is raised by the schema-editor backend, meaning if you try an 
`AlterField` with this change, you'd hit the error.

Another possibility might be to use the `SeparateDatabaseAndState` 
operation to create a migration that has no effect on the schema, but just 
updates the Python state for the field. Since you've already made the 
necessary db schema changes simply by adding the through model itself, this 
should work fine.

You could also go back and edit the field definition in whichever migration 
initially created it. This would probably work, but it would cause problems 
for any `RunPython` migrations since then that used that field (because now 
they'd try to use the through table instead), including your own data 
migration that you just created prior to this. So probably not a good 
option.
 

> (Not so important, but out of curiosity: This won't get us rid of the 
> old, implicit intermediate table, will it?) 
>

No. You could add another RunSQL migration to remove this table using raw 
SQL.

Overall I think it might be simpler to go with your initial approach. I'd 
first rename the old field to some other temporary name (you don't have to 
update any other code to use this name, as you'll commit all of these 
migrations in one commit, so nothing but the following data migration ever 
needs to know anything about this temporary name), then add the new field 
with through table (using the original field name), then migrate data 
(using either RunPython or RunSQL), then remove the old field. I think this 
will work fine, and it should also remove the old auto-created through 
table.

Good luck! I think this is definitely an area where the migrations system 
could help a bit more.

Carl

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/e987cf79-358d-4fdc-bac5-5131a19a25c1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to