你们好,我是言淦,我今天带来的文章是《Django4-一对一,一对多,多对多关系》,但愿能给大家带来帮助!python
环境: Django 2.2.1 + Python 3.6.7sql
显然,关系型数据库的强大之处在于各表之间的关联关系。 Django提供了定义三种最多见的数据库关联关系的方法:一对一,一对多,多对多。shell
典型的例子有一个学生对应一张身份证, 一张身份证对应一个学生。 又或者Dj文档的例子, 一个地点(Place)对应一个餐厅(Restaurant)。在Dj中,一对一关系使用OneToOneField来关联, 关联后,地点表能够查询餐厅表的数据,餐厅表也能够查询地点表的数据。数据库
例子: docs.djangoproject.com/zh-hans/2.2…django
典型的例子有一个班级拥有多个学生, 一个学生只能属于某个班级。 又或者Dj文档的例子, 一个做者(Reporter)能够写多篇文章(Article),而一篇文章只属于一个做者。在Dj中,一对多关系使用ForeignKey来关联。bash
注意, 正向查询是文章表来查做者表的数据, 反向查询是做者表来查文章表的数据。测试
官方文档demo测试spa
# R表->R表, A表->A表
# 新建应用associatest, 假定应用已注册
$ python manage.py makemigrations associatest
# 新建Model(与官方文档一致)
https://docs.djangoproject.com/zh-hans/2.2/topics/db/examples/many_to_one/
# 数据迁移效果(makemigrations+sqlmigrate+migrate)
1.表名是”应用名_Model名“的形式, 好比associatest_reporter
2.若是没有声明主键,则会自动加上主键,主键名为id
3.A表的外键名是reporter_id, 与R表的主键(id)关联
# R表增长数据(不会受到A表的影响)
$ python manage.py shell
>>> from associatest.models import Reporter
>>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r.save()
>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
>>> r2.save()
# A表增长数据(会受到R表的影响,对应的reporter要存在)
>>> from associatest.models import Article
>>> from datetime import date
>>> a = Article(id=None, headline="test", pub_date=date(2005, 7, 27), reporter=r)
>>> a.save()
# R表筛选数据,获得是一个queryset(条件是A表的字段)
>>> Reporter.objects.filter(article=1)
<QuerySet [<Reporter: John Smith>]>
>>> Reporter.objects.filter(article__headline='test')
<QuerySet [<Reporter: John Smith>]>
# A表筛选数据
>>> Article.objects.filter(reporter__first_name='John')
<QuerySet [<Article: test>]>
# R表查询A表数据(filter获得的是一个queryset, get获得的是一个对象)
>>> r3 = Reporter.objects.get(first_name='John')
>>> r3.Article__set().get(headline='test').id
# A表查询R表数据
>>> a.reporter.first_name
'John'
>>> a.reporter.id
1
# 字段参数
- to_field: 默认状况下reporter字段会关联到R表的主键,但能够经过to_field指定R表的其余字段,前提是指定的字段必须是unique的。
- related_name: 指定反向查询用的字段, 反向查询指R表查A表, 默认字段是Article__set()。 若是不但愿反向查询,可将related_name赋值为'+'。
- on_delete: 指定外键被删除时的一些行为
- on_delete=CASCADE: 默认选项, 级联删除(可是model.delete方法是不会删除关联model的数据的,详情查看官方文档)
- PROTECT: 保护模式,若是采用该选项,删除的时候,会抛出ProtectedError错误。
- SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank = True, null = True, 定义该字段的时候,容许为空。
- SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,因此定义外键的时候注意加上一个默认值。
- SET(): 自定义一个值,该值固然只能是对应的实体了
- DO_NOTHING: 不作任何事
- db_column: reporter做为A表的外键, 其在数据表的字段名称会被命名为reported_id(加后缀_id),若是你想避免这种状况, 能够用db_column参数指定字段名称。
复制代码
典型的例子是一个老师能够教多个班级, 一个班级能够被多个老师教。又或者Dj文档的例子, 一个出版社(Publication)能够发布多篇文章(Article),而一篇文章能够被多个出版社发布。在Dj中,多对多关系使用ManyToManyField来关联。code
docs.djangoproject.com/zh-hans/2.2…对象
Django关系模型只公开上述三种模型, OneToOneRel, ManyToOneRel, ManyToManyRel 是这三者内部使用的类。
Django_外键查询和反向查询: www.jianshu.com/p/20e078a71…
Django外键字段参数: docs.djangoproject.com/zh-hans/2.2…