ManyToMany field rename

933 views
Skip to first unread message

grahamu

unread,
Nov 3, 2009, 5:12:03 PM11/3/09
to South Users
Hi Andrew. I've had great success with add-schema/manipulate-data/
remove-schema migrations for simple cases. Now I hope to both rename a
class referenced by a ManyToMany field, and rename the referencing
field name as well. So given:

class Original:
...

class Reference:
originals = models.ManyToMany('Original')

I'd like to move to:

class Rename:
...

class Reference:
renames = models.ManyToMany('Rename')

While this looks like a simple renaming problem, I need the original
data, including pks, to stay intact. What is the best method to
accomplish this?

Andrew Godwin

unread,
Nov 3, 2009, 5:31:21 PM11/3/09
to south...@googlegroups.com
This one's a bit more tricky - ManyToMany fields are "special" in a few ways.
What I suggest is:

- Making the "through" model explicit (i.e. have a OriginalReferenceJoin
model), and making sure this points at the old table (using a Meta and
db_table), and then set it using through= on the two ManyToManys.
- Make sure this model has foreignkeys pointing at the other two tables, with
db_column set to the old column names.
- Then, rename the old model Original to Rename, and the db_column and
db_table should keep everything pointing at the right place.

You might also be able to get away with it by just renaming Original to Rename
and adding a Meta: db_table = with the Original table name.

Andrew

grahamu

unread,
Nov 4, 2009, 1:23:52 PM11/4/09
to South Users
Thanks for your speedy response Andrew.
I decided to take the "easy" route with your second suggestion. The
steps necessary included:

1. Rename class Original to class Rename in the models.py file.

2. Specify the "db_table" attribute for the M2M field:
class Reference:
renames = models.ManyToMany('Rename',
db_table='appname_reference_originals')

3. Create a migration for the changes. Change the automatically
inserted db.delete_table()/db.add_table() to db.rename_table():
db.rename_table('appname_original', 'appname_rename')

4. In the migration created above, manually include a change to the
intermediate M2M table:
db.rename_column('appname_reference_originals', 'original_id',
'rename_id')

I believe without this last change Django will choke.

Graham
Reply all
Reply to author
Forward
0 new messages