Django4-一对一,一对多,多对多关系

大家好,我是言淦,我今天带来的文章是《Django4-一对一,一对多,多对多关系》,希望能给你们带来帮助!

环境: Django 2.2.1 + Python 3.6.7

显然,关系型数据库的强大之处在于各表之间的关联关系。 Django提供了定义三种最常见的数据库关联关系的方法:一对一,一对多,多对多。

一对一

典型的例子有一个学生对应一张身份证, 一张身份证对应一个学生。 又或者Dj文档的例子, 一个地点(Place)对应一个餐厅(Restaurant)。在Dj中,一对一关系使用OneToOneField来关联, 关联后,地点表可以查询餐厅表的数据,餐厅表也可以查询地点表的数据。

例子: docs.djangoproject.com/zh-hans/2.2…

一对多

典型的例子有一个班级拥有多个学生, 一个学生只能属于某个班级。 又或者Dj文档的例子, 一个作者(Reporter)可以写多篇文章(Article),而一篇文章只属于一个作者。在Dj中,一对多关系使用ForeignKey来关联。

注意, 正向查询是文章表来查作者表的数据, 反向查询是作者表来查文章表的数据。

官方文档demo测试

# 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='[email protected]')
>>> r.save()
>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='[email protected]')
>>> 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来关联。

docs.djangoproject.com/zh-hans/2.2…

OneToOneRel 和 OneToOneField区别:

Django关系模型只公开上述三种模型, OneToOneRel, ManyToOneRel, ManyToManyRel 是这三者内部使用的类。

参考:

Django_外键查询和反向查询: www.jianshu.com/p/20e078a71…

Django外键字段参数: docs.djangoproject.com/zh-hans/2.2…

转载于:https://juejin.im/post/5cf68086e51d455c8838e116

猜你喜欢

转载自blog.csdn.net/weixin_33916256/article/details/91460013