七、Django的orm之多表操作(一)
多表操作
三种关系:一对一,一对多,多对多
一、数据准备,创建表模型
-
配置settings,连接到数据库
# settings更改配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'orm03',
'HOST':'127.0.0.1',
'PORT':3306,
'USER':'root',
'PASSWORD':'123'
}
}项目中的init写入:
import pymysql
pymysql.install_as_MySQLdb() -
在应用中的models.py创建模型
from django.db import models比较常用的信息放到这个表里面
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
age=models.IntegerField()
authorDetail=models.OneToOneField(
to="AuthorDetail",
to_field="nid",
on_delete=models.CASCADE # on_delete=models.SET_NULL()设置不级连删除,对方删除后,自己设置为空
)
# 与AuthorDetail建立一对一的关系(OneToOneField),一对一的这个关系字段写在两个表的任意一个表里面都可以
# 就是foreignkey+unique,只不过不需要我们自己来写参数了,并且orm会自动帮你给这个字段名字拼上一个_id,数据库中字段名称为authorDetail_id不常用的放到这个表里面
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday=models.DateField()
# telephone=models.BigIntegerField() 不方便以后查询,需要再转str查,不如直接用str类型
telephone=models.CharField(max_length=30)
addr=models.CharField(max_length=64)
# 与Author建立一对一的关系(OneToOneField这个关系字段写在两个表的任意一个表里面都可以)class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
email=models.EmailField() # 相当于CharField,后期可多一层校验规则,判断是否是xx.@...这样的邮箱地址多对多的表关系,在mysql的时候建立这种关系,需要手动创建一个第三张表,然后写上两个字段,每个字段外键关联到另外两张多对多关系的表;orm的manytomany自动帮我们创建第三张表,两种方式建立关系都可以,以后的学习我们暂时用orm自动创建的第三张表,因为手动创建的第三张表我们进行orm操作的时候,很多关于多对多关系的表之间的orm语句方法无法使用
如果你想删除某张表,你只需要将这个表注销掉,然后执行那两个数据库同步指令就可以了,自动就删除了。
与Publish建立一对多的关系
与Author建立多对多的关系
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=32)
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2)
publish=models.ForeignKey(
to="Publish",
to_field="nid",
on_delete=models.CASCADE
)
# 与Publish建立一对多的关系,外键字段建立在多的一方,字段publish如果是外键字段,那么它自动是int类型foreignkey里面可以加很多的参数,to指向表,to_field指向你关联的字段,不写这个,默认会自动关联主键字段,on_delete级联删除
字段名称不需要写成publish_id,orm在翻译foreignkey的时候会自动给你这个字段拼上一个_id,这个字段名称在数据库里面就自动变成了publish_id
与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表,并且注意一点,你查看book表的时候,你看不到这个字段,因为这个字段就是创建第三张表的意思,不是创建字段的意思,所以只能说这个book类里面有authors这个字段属性
authors=models.ManyToManyField(to='Author')
# 注意不管是一对多还是多对多,写to这个参数的时候,最后后面的值是个字符串,不然你就需要将你要关联的那个表放到这个表的上面
总结:
创建表:一对一:# OneToOneField
xx = models.OneToOneField(
to='表名',
to_field='字段名',
on_delete=models.CASCADE
)
# to_field可以不写,默认是关联到另一张表的主键
# on_delete在1.x版本的django中不用写,默认是级联删除的,2.x版本的django要写
# on_delete=models.SET_NULL()设置不级连删除,对方删除后,自己设置为空一对多:# ForeignKey
xx = models.ForeignKey(
to='表名',
to_field='字段名',
on_delete=models.CASCADE
)多对多:# ManyToManyField
xx = models.ManyToManyField(to='另外一个表名') #这是自动创建第三表
# 还可以手动创建第三张表,(用在还有其他一些自己的字段的时候,暂时忽略)
# class BookToAuthor(models.Model):
# book_id = models.ForeignKey(to='Book')
# author_id = models.ForeignKey(to='Author')
# xx = models.CharField(max_length=12)注意:不管是一对多还是多对多,写to这个参数的时候,最后后面的值是个字符串,不然你就需要将你要关联的那个表放到这个表的上面
-
执行数据库同步指令:
python manage.py makemigrations
python manage.py migrate
结果如下:

二、关系表添加记录

拓展一种添加数据的方式,是django内部提供的一个后台管理系统
-
创建一个超级用户:
python manage.py createsuperuserUsername (leave blank to use 'administrator'): yangzm
Email address:
Password: 94211314ming. -
访问127.0.0.1:8000/admin/,使用刚注册好的用户名、密码,登录后台管理系统

-
在应用app01下的admin.py注册我们要用的表
from django.contrib import admin
from app01 import models # 导入modelsRegister your models here.
admin.site.register(models.Author) # admin.site.register方法注册
admin.site.register(models.Publish)
admin.site.register(models.Book)
admin.site.register(models.AuthorDetail) -
重新运行项目,就会发现表已经在后台的管理系统当中了

-
点击里面的添加按钮,根据要求,就可以添加数据了

-
增
-
一对一表的增加
一对一关联的表是:Author表的authorDetail字段关联的 AuthorDetail表的nid字段
def query(request):new_author_detail = models.AuthorDetail.objects.create(
birthday='1996-02-14',
telephone='188753698755',
addr='天界大陆'
)
# 方式1:
models.Author.objects.create(
name='liangdao',
age='26',
authorDetail=new_author_detail # 直接等于对象
)new_author_obj = models.AuthorDetail.objects.create(
birthday='1886-02-14',
telephone='18615724935',
addr='幽暗密林'
)
# 方式2:(常用)
models.Author.objects.create(
name='baobao',
age='55',
authorDetail_id=new_author_obj.nid # 把对象的id属性关联起来
) -
一对多的增加
一对多关联的表是:Book表的publish字段关联的 Publish表的nid字段
# 方式1:
models.Book.objects.create(
title='回村的诱惑',
publishDate='2018-12-12',
price=88.88,
publish=models.Publish.objects.get(nid=1)
)
# 方式2:(常用)
models.Book.objects.create(
title='回村的诱惑2',
publishDate='2000-11-11',
price=45,
publish_id=models.Publish.objects.get(nid=1).nid
) -
多对多的增加
多对多关联的表是:Book表的authors字段关联的 Author表的nid字段
# 方式1:常用
book_obj = models.Book.objects.get(nid=1)
book_obj.authors.add([1,2])
# 方式2:
author1 = models.Author.objects.get(nid=1)
author2 = models.Author.objects.get(nid=3)
book_obj = models.Book.objects.get(nid=2)
book_obj.authors.add([author1, author2])
- 删
一对一和一对多的删除和单表删除是一样的
-
一对一的删
# Author表一对一关联AuthorDetail表
models.AuthorDetail.objects.get(nid=2).delete()
# 当AuthorDetail表删除数据时,会影响到Author表,因为级联删除
models.Author.objects.get(nid=4).delete()
# 当Author表删除数据时,不会影响到AuthorDetail表
注意:- 表一关联表二,做了级联,表二删除,表一跟着删除
- 表一关联表二,没做级联,表二删除,表一报错
- 表一关联表二,无论做没做级联,表一删除数据,都不会影响到表二
-
一对多的删
# Book表一对多关联Publish表
models.Publish.objects.get(nid=2).delete()
# Publish表删除数据,影响到Book表
models.Book.objects.get(nid=7).delete()
# Book表删除数据,不会影响到Publish表 -
多对多关系的删除
实际上就是去删除多对多自动生成的表中的关系的记录
# Book表多对多的关联Author表
book_obj = models.Book.objects.get(nid=3)
book_obj.authors.remove(3)
# 先找到book里id是3的书,然后通过authors属性删除作者id是3的数据book_obj = models.Book.objects.get(nid=3)
book_obj.authors.remove(*[2,3])
# 先找到book里id是3的书,然后通过authors属性删除作者id是2和3的数据book_obj = models.Book.objects.get(nid=3)
book_obj.authors.clear()
# 先找到book里id是3的书,然后通过authors属性找到关系表,删除所有id是3的书数据book_obj = models.Book.objects.get(nid=3)
book_obj.authors.clear()
book_obj.authors.add(*[1,])
# 先删除所有id是3的书数据,然后给id是3的书加入一个id是1的作者book_obj = models.Book.objects.get(nid=3)
book_obj.authors.set('1')
# 同样完成上述需求,先清空再添加(set必须给个参数,否则报错)book_obj = models.Book.objects.get(nid=3)
book_obj.authors.set(['5','6'])
# 删除然后更新,添加多个
注意:- Book表删除数据,会影响到关系表的数据
- Author表删除数据,也同样会影响到关系表的数据
- 更新
-
一对一
models.Author.objects.filter(nid=6).update(
name='baoge',
age='16',
authorDetail=models.AuthorDetail.objects.get(nid=5)
# authorDetail_id = 4 两种方式
) -
一对多
models.Book.objects.filter(pk=6).update(
title='回娘家的诱惑',
price=188,
publish=models.Publish.objects.get(pk=2)models.Publish.objects.filter(pk=2).update(
id=4, # 没有级联更新,报错!!
)注:默认级联删除,级联更新没有默认
-
多对多
# 就是setbook_obj = models.Book.objects.get(nid=3)
book_obj.authors.set('1')
# 同样完成上述需求,先清空再添加(set必须给个参数,否则报错)book_obj = models.Book.objects.get(nid=3)
book_obj.authors.set(['5','6'])
# 删除然后更新,添加多个
浙公网安备 33010602011771号