django adding a ManyToMany field/table to existing

2019-02-21 19:55发布

问题:

I have an existing project with models (Users and Books). I would like to add a ManyToMany(M2M) field to the existing model Books, but the syncbb command does not do this.

Details: Books already has a FK field that maps to User, and I want to add a new M2M field (readers) that also maps to User. As you know, Django's syncdb only cares about tables, so adding a normal field is easy, but a M2M requires a new join table (app_books_user), so shouldn't syncdb cmd add this like any other new table? It created my other joined table for the Book's 'sellers' field.

When I ran syncdb, I initially received an error instructing me to use the 'related_name' argument to help differentiate the two references to User. I added those. However, when I run syncdb again, it does not create the new join table (but it's now error-free). The new field exists when I view it via the Shell, but can't use it b/c the join table doesn't exist. I looked at the sql code via 'sqlall' cmd and it prints out the SQL for the new table, but it doesn't get executed.

What am I missing? Should I just force the SQL (from the sqlall) via my database browser? Will that have any repercussions? Code follows:

Models.py

from django.contrib.auth.models import User

class Seller(models.Model):
    ...

class Books(models.Model):

    name=models.CharField(max_length=50)
    author=models.ForeignKey(User, related_name='creator')
    readers=models.ManyToManyField(User, blank=True, related_name='viewers')
    sellers=models.ManyToManyField(Seller)

Thank you

回答1:

syncdb does not modify existing tables (models). What's going on is that even though adding a M2M does not modify a table (it should just add a join table), the syncdb is not creating the new table because it sees that the model is already in the db and it is skipping it. See the syncdb docs

[syncdb] Creates the database tables for all apps in INSTALLED_APPS whose tables have not already been created.

It is a bit confusing, since technically this table hasn't been created, but the behavior makes sense "Has the table for this model been created? Yep! Then don't sync it."

In general, django does not provide a mechanism to migrate database schemas (ie add columns and such). So, you have to do that sort of a thing via raw SQL or by using a third party tool. I highly recommend checking out South.