理解django的多对多ManyToManyField
对于第一次碰到django这样类activerecord的ORM,初学者可能比较疑惑的是ManyToManyField这个字段。老鸟可以绕开,这里拿djangobook没有说明的地方来仔细解释下。
from django.db import modelsclass Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField()class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField()class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField()
python manage.py sql books查看生成的表结构
BEGIN;CREATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(30) NOT NULL, "address" varchar(50) NOT NULL, "city" varchar(60) NOT NULL, "state_province" varchar(30) NOT NULL, "country" varchar(50) NOT NULL, "website" varchar(200) NOT NULL);CREATE TABLE "books_author" ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(40) NOT NULL, "email" varchar(75) NOT NULL);CREATE TABLE "books_book" ( "id" serial NOT NULL PRIMARY KEY, "title" varchar(100) NOT NULL, "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED, "publication_date" date NOT NULL);CREATE TABLE "books_book_authors" ( "id" serial NOT NULL PRIMARY KEY, "book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED, "author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED, UNIQUE ("book_id", "author_id"));CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id");COMMIT;#首先是创建一个book,book创建之后才能添加联系表,这是显然的book = Book()book.save()#添加三个作者,传如一个列表book.authors = Author.objects.all()[0:3]#或者添加一个作者,传入一个实例book.authors.add(Author.objects.all()[0])#最后是savebook.save()
book.authors.all()author.book_set.all()
select publisher_author.* from publisher_author, author where publisher_author.author_id = author.id
select * from publisher where publisher.id in (select publisher_id from publisher_author, author where publisher_author.author_id = author.id)