1,模型定义
models.py的例子:
1 class Author(models.Model): 2 name=models.CharField(max_length=20) 3 4 class Book(models.Model): 5 id=models.AutoField(primary_key=True) 6 name=models.CharField(max_length=50) 7 author=models.ForeignKey(Author) 8 length=models.IntegerField()
主键的唯一性:如果没有设置主键,django会设置一个自增id,其类型为django的AutoField(一个自增的整数)。
当然,你可以在变量的属性中添加primary_key=True让其成为主键,这意味着这个变量的值必须是唯一的。还有一个类似的属性unique=True,这也能保证变量的唯一性,不过你不需要将它作为主键。
2.模型之间的关系
外键
1 class Author(models.Model): 2 name=models.CharField(max_length=20) 3 4 class Book(models.Model): 5 name=models.CharField(max_length=50) 6 author=models.ForeignKey(Author)
需注意,一定要先把被引用的类放前面,否则Author变量名是不会被Book类中的ForeignKey识别的,当然也可以通过字符来替代,这样就不必担心顺序先后的问题,如下:
1 class Book(models.Model): 2 name=models.CharField(max_length=50) 3 author=models.ForeignKey("Author") 4 5 class Author(models.Model): 6 name=models.CharField(max_length=20)
ForeignKey只定义了关系的一端,不过另一端却能根据关系找到,外键从关系上将是“多对一”关系,多个子对象引用一个父对象。如下例子:
1 #models.py 3 class Book(models.Model): 4 title=models.CharField(max_length=50) 5 author=models.ForeignKey("Author")
#author=models.ForeignKey("Author",related_name="books") 7 class Author(models.Model): 8 name=models.CharField(max_length=20) 9 10 #views.py 12 def test(request): 13 book=Book.objects.get(title="Moby dic") 14 author=book.author 15 books=author.book_set.all()
#books=author.books.all()
从上面可以看到Author到Book的反向关系是通过Author.book_set表示的。
上面的例子中,我们可以再Foreignkey里指定的related_name参数改变它的名字,如果我们把author定义成ForeignKey("Author",related_name="books")的话,最后就访问author.books,而不是author.book_set了。
多对多关系
外键通常只能表示一对一或多对一关系,如上我们只能表示一本书只能有一位作者。但是如果一本书有多个作者的情况如何表示呢?这时就需要多对多关系了,dango为这种情况提供了ManyToManyField。你再关系的一段定义它,把要关联的类传递进来,ORM会自动在另一端生成使用这个关系必要的方法和属性(和ForeignKey一样,通常生成一个_set manager对象)。
我们将上面的一对多关系改成多对多关系,如下:
1 class Book(models.Model): 2 title=models.CharField(max_length=50) 3 authors=models.ManyToManyField("Author") 4 6 class Author(models.Model): 7 name=models.CharField(max_length=20)
我们查看数据库后多一张表:
mysql> show tables like 'blog%';
+------------------------+
| Tables_in_mydb (blog%) |
+------------------------+
| blog_author |
| blog_book |
| blog_book_authors |
+------------------------+
4 rows in set
1 mysql> desc blog_book; 2 +-------+-------------+------+-----+---------+----------------+ 3 | Field | Type | Null | Key | Default | Extra | 4 +-------+-------------+------+-----+---------+----------------+ 5 | id | int(11) | NO | PRI | NULL | auto_increment | 6 | title | varchar(50) | NO | | NULL | | 7 +-------+-------------+------+-----+---------+----------------+ 8 2 rows in set 9 10 mysql> desc blog_author; 11 +-------+-------------+------+-----+---------+----------------+ 12 | Field | Type | Null | Key | Default | Extra | 13 +-------+-------------+------+-----+---------+----------------+ 14 | id | int(11) | NO | PRI | NULL | auto_increment | 15 | name | varchar(20) | NO | | NULL | | 16 +-------+-------------+------+-----+---------+----------------+ 17 2 rows in set 18 19 mysql> desc blog_book_authors; 20 +-----------+---------+------+-----+---------+----------------+ 21 | Field | Type | Null | Key | Default | Extra | 22 +-----------+---------+------+-----+---------+----------------+ 23 | id | int(11) | NO | PRI | NULL | auto_increment | 24 | book_id | int(11) | NO | MUL | NULL | | 25 | author_id | int(11) | NO | MUL | NULL | | 26 +-----------+---------+------+-----+---------+----------------+ 27 3 rows in set
我们可以从sql中查出新建的表blog_book_authors中的字段实际上是两个外键,如下:
1 mysql> show create table blog_book_authors; 2 +-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 3 | Table | Create Table | 4 +-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 5 | blog_book_authors | CREATE TABLE `blog_book_authors` ( 6 `id` int(11) NOT NULL AUTO_INCREMENT, 7 `book_id` int(11) NOT NULL, 8 `author_id` int(11) NOT NULL, 9 PRIMARY KEY (`id`), 10 UNIQUE KEY `blog_book_authors_book_id_author_id_0a5bb3b3_uniq` (`book_id`,`author_id`), 11 KEY `blog_book_authors_book_id_35eae5ed` (`book_id`), 12 KEY `blog_book_authors_author_id_fa034e3d` (`author_id`) 13 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 | 14 +-------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 15 1 row in set
通过如下代码查询:
1 book=Book.objects.title(title="python developement") 2 authors=book.authors_set.all() 3 books=authors[2].book_set.all()
上面的代码和下面是一样的,通过through你可以手工管理中间类上的额外变量,同时还能方便的管理关系两端:
1 class Author(models.Model): 2 name=models.CharField(max_length=20) 3 4 class Book(models.Model): 5 title=models.CharField(max_length=50) 6 # author=models.ForeignKey("Author") 7 authors=models.ManyToManyField("Author",through="Authoring") 8 9 class Authoring(models.Model) 10 coll_type=models.CharField(max_length=100) 11 book=models.ForeignKey("Book") 12 author=models.ForeignKey("Author")
继承模型
抽象基础类和多表继承
抽象基础类:
是纯python的继承,这样变量和方法从基类继承下来,子类在数据库的表还是复制了基类的变量。
1 class Author(models.Model): 2 name=models.CharField(max_length=20) 3 4 class Book(models.Model): 5 title=models.CharField(max_length=100) 6 genre=models.CharField(max_length=40) 7 num_pages=models.IntegerField() 8 authors=models.ManyToManyField("Author") 9 10 def __unicode__(self): 11 return self.title 12 13 class Meta: #只作为一个抽象类,只能被继承,不能被实例化 14 abstract=True 15 16 class SmithBook(Book): 17 authors=models.ManyToManyField(Author,limit_choices_to={'name__endswith':'Smith'})
SmithBook的定义和下面是一样的:
1 class SmithBook(Book): 2 title=models.CharField(max_length=100) 3 genre=models.CharField(max_length=40) 4 num_pages=models.IntegerField() 5 authors=models.ManyToManyField(Author,limit_choices_to={'name__endswith':'Smith'}
def __unicode__(self):
return self.title
如果基类用到了related_name参数来设置ForeignKey这样的变量的话,需要用一些字符串格式化来避免子类的名字发生冲突,不要使用related_employess之类的常见字符串,而应该用%(class)s,这样“related_%(class)s“,子类的名字就能被正确替换,避免发生冲突。