1.Foreign Key
1)ForeignKey用来定义多对一得关系,ForeignKey的参数是主键的类,就像文章开始
用的例子,Book.publisher的ForeignKey参数就是Publisher类。
2)对象也可以和自身关联,用mdels.ForeignKey('self'),这样就建立了一种递归关系。
3)在2)中用到了字符串,是的,外键参数可以用字符串的,这个在参数类还没有定义的时候
尤其适用,比如在Publisher类没有定义时,你完全可以用models.ForeignKey('Publisher')
注意:只能对同一个models.py文件中的模型适用字符串引用,其他的或者导入的模型不可用。
4)访问
在文章开始给出的models可以看出,Book中有外键publisher
如下代码所示,通过book的object访问publisher同访问正常field没区别。
但是通过主键Publisher访问book时,需要用book_set的形式。
即:主键中模型类名的小写+_set
>>> from website.books import models
>>> b = models.Book.objects.get(tille='djangobook')
>>> p=models.Publisher.objects.filter(name='Apress')[0]
>>> b.publisher
<Publisher: name:Apress, address:2855 Telegraph Avenue>
>>> p.book_set.all()
[<Book: djangobook>, <Book: pythonbook>]
2.ManyToMany
1)ManyToManyField放在哪个模型中
分析文章开始给出的例子:一个作者可以写多本书,一本书可以有多本书
这个Field放在Book中还是Author中都可以。但是不能两个都放。
2)关于自关联以及字符串参数等同ForeignKey一样。
3)访问同ForeignKey类似
这里说明一点。book_set属性一定是author的一条记录而不能是QuerySet
在Django中,many-to-many的中间关系表是自动创建的,如果你要指定一个自己的Model类作为关系对象,只需要在需要获取对端的Model类中增加一个ManyToManyField属性,并指定though参数。比如现在我们已经有了这样两个many-to-one关系,LineItem --->Product, LineItem-->Order, 如果需要从Product直接获取关联的Order,只需要增加一行,最终的Product如下:
class Product(models.Model):
title = models.CharField(max_length=100,unique=True)
description = models.TextField()
image_url = models.URLField(max_length=200)
price = models.DecimalField(max_digits=8,decimal_places=2)
date_available = models.DateField()
orders = models.ManyToManyField(Order,through='LineItem')
之后就可以通过product对象直接找到包含该产品的订单:
$ python manage.py shell
>>> from depot.depotapp.models import Product
>>> p = Product(id=1)
>>> p.orders
>>> p.orders.all()
[, ]
例子:有出版商,作者,和书。一本书有多个作者,只有一个出版商。
- from django.db import models
- class 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()
使用ManyToManyField的好处是不是就是省去了创建一个简单联系表(如果不满足于这么简单的表,也可一通过through参数来指明存在的表)?使用它我们还可以做到通过把一张表中某键值在另一张表中全部映射的对象找出来。比如把某书的所有作者,或者某作者的所有书找出来。
- book.authors.all()
- author.book_set.all()
如果只是用简单的三张表,表中关系为一对多的外键的话,下面是和有多对多关系的sql比较:
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) 多对多关系只是帮我们多做了一步嵌套子查询,并包装成publisher集
下面是建立对象间的关联:
from django.db import models |
02 |
03 | class User(models.Model): |
04 | name = models.CharField(max_length = 30 ) |
05 |
06 | class Group(models.Model): |
07 | name = models.CharField(max_length = 30 ) |
08 | member = models.ManyToMany(User,through = 'Friendship' ) |
09 |
10 | class Friendship(models.Model): |
11 | #通过through属性建立了Group与User之间的关系,在Friendship中必须有两个外键与其绑定 |
12 | owner = medels.ForeignKey(User) |
13 | group = medels.ForeignKey(Group) |
这种方法比起前一种关系结构更明确,但是操作起来需要的语句更加多一些。即当User和Group的对象中有任意一个被删除,这种关系自动解除,虽然这里举的例子并不能很好诠释。