您的位置:首页 > 编程语言 > Go语言

Django模型层多表操作

2020-06-02 22:45 232 查看

目录

1.创建表模型

'''
(一)多表查询
一对一:models.OneToOneField(to_field='id',to='Authordatil')

一对多:(外键设置唯一性)
models.ForeignKey(to='Publish',to_field='id')

多对多:自动生成第三张表
models.ManyToManyField(to='Author')

(二)创建表模型
作者与详情  ( 一对一 )
书与作者( 多对多 )
出版社与书(一对多 )

出版社:id name  add  email
书: id  name  price  publish

作者: id  name  sex  authordatil
详情: id  photo  address

'''

from django.db import models

# Create your models here.

class Publish(models.Model):  
id = models.AutoField(primary_key=True)   # 主键
name = models.CharField(max_length=32)
address = models.CharField(max_length=64)
email = models.EmailField()

def __str__(self):
return '%s,%s,%s'%(self.name,self.address,self.email)

class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5,decimal_places=2)
# 出版社与书( 一对多 )外键要设置唯一性,关联的表,关联的字段
publish = models.ForeignKey(to='Publish',to_field='id')
# 书与作者( 多对多 )
authors = models.ManyToManyField(to='Author')

def __str__(self):
return self.name

class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
choices = ( (0,"女"),(1,"男") )
sex = SmallIntegerField( choices=choices, default=0 )
# 作者与详情 ( 一对一 )
authordatil = models.OneToOneField(to_field='id',to='Authordatil')
def __str__(self):
return self.name
class Authordatil(models.Model):
id = models.AutoField(primary_key=True)
photo = models.CharField(max_length=32)
address = models.CharField(max_length=32)
  • id 字段是自动添加的
  • 对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名
  • 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

2.添加/删除/修改表记录

  • 批量插入
# 批量插入 bulk_create
li = []
for i in range(100):
li.append(models.Book(name='图书%s'%i,price=10+i))  # 生成100个对象
models.Book.objects.bulk_create(li)  # 参数为列表,列表里为100个对象,一次插入100条
  • 一对一 增/删/改 数据
# 增
Authordatil = Authordatil.objects.create(photo=121212121,address='东莞')
# 改
auther = Auther.objects.filter(name = '西游记').update( publish_id=1 )
# 先查
auther = Auther.objects.filter("name" = "西游记").first()
auther.name = "东游记"  # 再改
auther.save()  # 最后保存
auther =Auther.objects.filter(name = '西游记').delete()  # 删除
  • 一对多 增/删/改 数据
#增:
# publish_id: 数字
book = Book.objects.create(name='三国',price=56,publish_id=1)
# publish: 对象
publish = Publish.objects.get(id=1)
book = Book.objects.create(name='西游记',price=26,publish=publish)
#改:
# publish_id: 数字
book = Book.objects.filter(name = '西游记').update( publish_id=1 )
# publish: 对象
publish = Publish.objects.get(id=3)
book = Book.objects.filter(name = '西游记').update(publish=publish)

#删:同单表查询一样
book = Book.objects.filter(name='西游记',price=22).delete()
  • 多对多 增/删/改 数据
'''
增:add ( obj1,obj2... )   可以传对象,可以传id,可以传多个
删:remove( obj1,obj2... )  可以传对象,可以传id,可以传多个

改:先清空,配置
清空: clear()  清空所有
配置:set()  里面传列表,里面可以是对象或者是id  *注意先清空,在配置
'''
#(五)多对多新增 (书 与 作者)
zxx = Author.objects.filter(name='zxx').first()
yxx = Author.objects.filter(name='yxx').first()
book = Book.objects.filter(name='西游记').first()
book.authors.add(yxx,zxx)
# 删:
lxx = Author.objects.filter(name='lxx').first()
zxx = Author.objects.filter(name='zxx').first()
book = Book.objects.filter(name='红楼梦').first()
book.authors.remove(lxx,zxx)
# 清空: clear()  清空所有
book.authors.clear()
# 配置:set()
lxx = Author.objects.filter(name='lxx').first()
zxx = Author.objects.filter(name='zxx').first()
book.authors.set([1,2])
book.authors.set([lxx,zxx])

3.基于对象的查询表记录(子查询)

  • 查询分析:正反向查询
'''
从关联字段的表出发,查向另外一张表  为正向,反之为反向
eg:
  正向: author---关联字段在author--->authordetail   ------>  按字段
  反向: authordetail------关联字段在author--->author  -----> 按表名小写
'''
  • 一对一 查询
# 正向(按字段名)
author = Author.objects.filter(name='lxx').first()
photo = author.authordatil.photo
# 反向(按表名小写)
authordatil = Authordatil.objects.filter(photo=166667878).first()
author_name = authordatil.author.name
  • 一对多 查询
# 正向(按字段名)
book = Book.objects.filter(name='茶社').first()
publish = book.publish
print(publish.name)
# 反向 ( 按 表名_set.all() )
publish = Publish.objects.filter(name='武汉出版社').first()
author = publish.book_set.all()
  • 多对多 查询
# 正向(按字段名)
book = Book.objects.filter(name='红楼梦').first()
author = book.authors.all()
# 反向( 按 表名_set.all() )
author = Author.objects.filter( name='lxx').first()
book = author.book_set.all()

4.基于双下划线查询表记录(连表查询)

# 正向查询  ( 按字段,跨表可以在filter,也可以在values中 )
photo = Author.objects.filter(name='lxx').values('authordatil__photo')
print(photo)
# 反向查询( 按表名小写,跨表可以在filter,也可以在values中 )
photo = Authordatil.objects.filter(author__name='lxx').values('photo')
print(photo)
# 正向连续跨表查询( 按字段,跨表可以在filter,也可以在values中 )
name = Publish.objects.filter(name='武汉出版社').values('book__authors__authordatil__photo')
# 反向连续跨表查询( 按表名小写,跨表可以在filter,也可以在values中 )
photo = Author.objects.filter(book__publish__name='武汉出版社').values('book__authors__authordatil__photo')
'''
练习一:

1 用orm插入6个作者详情,插入6个作者
2 用orm插入6个出版社
3 用orm插入8本书,4种用publish=对象的形式,4种用publish_id=id的形式
4 两种形式修改书的出版社
5 基于对象查询,地址为山东的作者的姓名 ( 一对一 )
6 基于对象查询,电话为13888888作者的性别 ( 一对一 )
7 基于双下划线查询,地址为山东的作者的姓名
8 基于双下划线查询,电话为13888888作者的性别
9 基于对象查询北京出版社出版的所有图书
9 基于对象查询南京出版社出版的价格大于20的图书(一对多)
10 基于对象查询图书名字叫红楼梦这本书的作者(多对多)
11基于对象查询作者名为lqz,出版的所有图书
12 基于对象查询作者名为lqz,出版的价格大于20的所有图书
13 基于对象查询图书名以红开头,所有的出版社信息
14基于对象查询图书名以红开头,出版社以社结尾的所有出版社地址
15 查询所有价格大于20的图书
16 查询所有价格大于20的图书所有的出版社
17 查询手机号以13开头,所有的作者
18查询手机号以13开头,所有作者出版的所有图书
19 查询图书价格在[19.9,56,77.9]内的所有图书
20 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者
21 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者的手机号
'''

# 4 两种形式修改书的出版社
#方法(1)
book = Book.objects.filter(name='红楼梦').first()
book.publish_id = 2
book.publish = publish
book.save()
# 方法(2)
publish = Publish.objects.filter(name='深圳出版社').first()
book = Book.objects.filter(name='红楼梦').first()
book.publish = publish
book.save()

# 5 基于对象查询,地址为山东的作者的姓名 ( 一对一 )
authordatil = Authordatil.objects.filter(address='山东').first()
name = authordatil.author.name

# 6 基于对象查询,电话为13888888作者的性别 ( 一对一 )
authordatil = Authordatil.objects.filter(photo =  133323223).first()
sex = authordatil.author.sex

# 7 基于双下划线查询,地址为山东的作者的姓名
authordatil = Authordatil.objects.filter(address='东京').values('author__name')

# 8 基于双下划线查询,电话为13888888作者的性别
sex = Authordatil.objects.first(photo=133323223).values('author__sex')

# 9 基于对象查询北京出版社出版的所有图书
publish = Publish.objects.filter(name='杭州出版社').first()
books = publish.book_set.all()

# 9 基于对象查询南京出版社出版的价格大于20的图书(一对多)
publish = Publish.objects.filter(name='杭州出版社').first()
book = publish.book_set.all().filter(price__gt=20)

# 10 基于对象查询图书名字叫红楼梦这本书的作者(多对多)
book = Book.objects.filter(name='红楼梦').first()
authors = book.authors.all().values('name')

# 11基于对象查询作者名为lqz,出版的所有图书
author = Author.objects.filter(name='lxx').first()
book = author.book_set.all()

# 12 基于对象查询作者名为lqz,出版的价格大于20的所有图书
author = Author.objects.filter(name='lxx').first()
book = author.book_set.all().filter(price__gt=31)

# 13 基于对象查询图书名以红开头,所有的出版社信息
book = Book.objects.filter(name__startswith='红').first()
publish = book.publish

# 14基于对象查询图书名以红开头,出版社以社结尾的所有出版社地址
book = Book.objects.filter(name__startswith='红').values_list('publish__address')
print(book)
publish = Publish.objects.filter(address__endswith='社').values_list('address')
for i in publish:
if i in book:
print(i)

# 15 查询所有价格大于20的图书
book = Book.objects.filter(price__gt=20).all()

# 16 查询所有价格大于20的图书所有的出版社
books = Book.objects.filter(price__gt=20)
for book in books:
publish = book.publish
print(publish)

# 17 查询手机号以13开头,所有的作者
#方法一:
authordatils = Authordatil.objects.filter(photo__startswith=13).values('author__name')
# 方法二:
authordatils = Authordatil.objects.filter(photo__startswith=13)
for authordatil in authordatils:
author = authordatil.author
print(author)

# 18查询手机号以13开头,所有作者出版的所有图书
#方法一:
books = Authordatil.objects.filter(photo__startswith=13).values('author__book__name')
# 方法二:
authordatils = Authordatil.objects.filter(photo__startswith=13).first()
# 拿到信息表 再到作者 再到书
book = authordatils.author.book_set.all()

# 19 查询图书价格在[19.9,56,77.9]内的所有图书
book = Book.objects.filter(price__in=[19.9, 56, 77.9]).all()

# 20 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者
# 方法一:
author = Book.objects.filter(price__in=[19.9, 56, 77.9]).values('authors')
# 方法二:
books = Book.objects.filter(price__in=[19.9, 56, 77.9])
for book in books:
author = book.authors.all()

# 21 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者的手机号
# 方法一:
books = Book.objects.filter(price__in=[19.9, 56, 77.9]).values('authors__authordatil__photo')
# 方法二:
books = Book.objects.filter(price__in=[19.9, 56, 77.9]).all()
for book in books:
authors = book.authors.all()
for author in authors:
photo = author.authordatil.photo
print(photo)
'''
作业二:
1 修改名字为lqz作者的手机号为12345678901
2 修改以红开头的图书的所有作者手机号为123321321
3 修改出版社是北京出版社出版的所有图书的价格为99.99
4 为红楼梦这本书,新增lqz,egon两个作者(两种方式)
5 更改红楼梦这本书的作者为lqz,xiaohou(两种方式)  ??????????
6 把上题lxx 换成 egon
6 删除红楼梦这本书xiaohou这个作者
7 清空红楼梦这本书所有作者
8 查询图书价格大于30的所有作者的名字
9 查询北京出版社出版的所有图书的作者名字
10 查询北京出版社出版的所有图书的作者手机号
11 查询西游记这本书所有作者的个数
12 查询北京出版社出版的图书个数
'''
# 1 修改名字为lqz作者的手机号为12345678901
author = Author.objects.filter(name='lxx').first()
authordatil = author.authordatil
authordatil.photo = 12345678901
authordatil.save()

# 2 修改以红开头的图书的所有作者手机号为123321321
books = Book.objects.filter(name__startswith='红')
for book in books:
authors = book.authors.all()
for author in authors:
authordatil = author.authordatil
authordatil.photo = 123321321
authordatil.save()

# 3 修改出版社是北京出版社出版的所有图书的价格为99.99
publish = Publish.objects.filter(name='长沙出版社').first()
books = publish.book_set.all()
for book in books:
book.price = 99.99
book.save()
print(book.price)

# 4 为红楼梦这本书,新增lqz,egon两个作者(两种方式)
# 方法一:
book = Book.objects.filter(name='红楼梦').first()
book.authors.add(4,5)
# 方法二:
egon = Author.objects.filter(name= 'egon').first()
wxx = Author.objects.filter(name='wxx').first()
book = Book.objects.filter(name='红楼梦').first()
book.authors.add(egon,wxx)

# 5 更改红楼梦这本书的作者为lqz,xiaohou(两种方式)  ??????????
book = Book.objects.filter(name='红楼梦').first()
authors = book.authors.clear()
print(authors)
lxx = Author.objects.filter(name='lxx').first()
zxx = Author.objects.filter(name='zxx').first()
book.authors.set([lxx,zxx])

#  把lxx 换成 egon
lxx =Author.objects.filter(name='lxx').first()
egon = Author.objects.filter(name='egon').first()
book = Book.objects.filter(name='边城').first()
book.authors.remove(lxx)
book.authors.set([egon,])

# 6 删除红楼梦这本书xiaohou这个作者
lxx = Author.objects.filter(name='lxx').first()
book = Book.objects.filter(name='红楼梦').first()
book.authors.remove(lxx)

# 7 清空红楼梦这本书所有作者
book = Book.objects.filter(name='红楼梦').first()
book.authors.clear()

# 8 查询图书价格大于30的所有作者的名字
book = Book.objects.filter(price__gt=30).values('authors__name','price')

# 9 查询北京出版社出版的所有图书的作者名字
publish = Publish.objects.filter(name='武汉出版社').values('book__authors__name')

# 10 查询北京出版社出版的所有图书的作者手机号
name = Publish.objects.filter(name='武汉出版社').values('book__authors__authordatil__photo')

# 11 查询西游记这本书所有作者的个数
book = Book.objects.filter(name='西游记').first()
con = book.authors.all().count()

# 12 查询北京出版社出版的图书个数
publish = Publish.objects.filter(name='武汉出版社').first()
con = publish.book_set.all().count()

5.聚合查询(aggregate)

from  django.db.models import Avg,Count,Min,Max,Sum
con = Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price'))

# 计算所有图书的平均价格
con = Book.objects.all().aggregate(Avg('price'))
print(con)
# 计算图书的最高价格
con = Book.objects.all().aggregate(Max('price'))
print(con)

# 计算图书的最高价格,最低价格,平均价格,总价
con = Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price'))
print(con)

6.分组查询(annotate)

'''
group by 谁,就以谁做基表,filter过滤,annotate取分组,values取值
values在前 以谁分组   values在后 表示 取值
filter在前 where条件   filter在后 表示 having
'''
# 统计每一本书作者个数
con = Book.objects.values('pk').all().annotate(c= Count('authors')).values('name','c')
print(con)
# 统计每一个出版社的最便宜的书
con = Publish.objects.values('pk').all().annotate(c= Min('book__price')).values('name','c')
print(con)

# 统计每一本以py开头的书籍的作者个数
con = Book.objects.filter(name__startswith='红').annotate(c=Count('authors')).values('name','c')
print(con)

# 统计每一本以py开头的书籍的作者个数--套用模板
con = Book.objects.filter(name__startswith='红').all().annotate(c=Count('authors')).values('name', 'c')
print(con)
# 查询各个作者出的书的总价格
con = Author.objects.annotate(c= Sum('book__price')).values('name','c')
print(con)

# 查询名字叫lqz作者书的总价格
con = Author.objects.filter(name='egon').annotate(c= Sum('book__price')).values('name','c')
print(con)

# 查询所有作者写的书的总价格大于30
con = Author.objects.annotate(c=Sum('book__price')).filter(c__gt=70).values('name', 'c')
print(con)

# 统计不止一个作者的图书
con =  Book.objects.annotate(c = Count('authors')).filter(c__gt=1).values('name','c')
print(con)

# F查询
# 查询评论数大于阅读数的书
from django.db.models import F
con = Book.objects.filter(commit_num__gt=F('read_num')).values('name')
print(con)
# 把所有书的评论数加1
con = Book.objects.all().update(commit_num=F('read_num')+1)
print(con)
# 把python这本书的阅读数减5
con = Book.objects.filter(name='红楼梦').all().update(read_num=F('read_num') -5 )
print(con)

7.F查询

'''
无法引用字段上的值,把字段名的值包裹起来,就能用了
from django.db.models import F

eg: Book.objects.filter(id=1).update(F("price")+1)  # 将第一本书的价格加一
'''

# 查询评论数大于阅读数的书
from django.db.models import F
con = Book.objects.filter(commit_num__gt=F('read_num')).values('name')
print(con)
# 把所有书的评论数加1
con = Book.objects.all().update(commit_num=F('read_num')+1)
print(con)
# 把python这本书的阅读数减5
con = Book.objects.filter(name='红楼梦').all().update(read_num=F('read_num') -5 )
print(con)

8.Q查询

from django.db.models import Q
# 与 &     或 |      非 ~
#Q查询: 基于关系运算     &与  |或  ~非
# &与 (默认为 与)

# 查看价格为15 与(且) 名字为金瓶眉的书
Book.objects.filter(Q(price=15),Q(name="金瓶眉”))
# 查看价格为15 或 名字为金瓶眉的书
Book.objects.filter(Q(price=15) | Q(name="金瓶眉”))
# 查看价格不为15 且 名不为金瓶眉的书
Book.objects.filter(~Q(price=15) & ~Q(name="金瓶眉”))

# 查询作者名字是lqz或者名字是egon的书
con = Author.objects.filter(Q(name='lxx') | Q(name='wxx')).values('book__name')
print(con)
# 查询作者不是lqz的书
# con = Author.objects.filter(~Q(name='lxx')).values('book__name')
con = Author.objects.filter(~Q(name='lxx')).values('book__name')
print(con)

con = Book.objects.filter(~Q(authors__name='lxx')).values('name')
print(con)
# 构建很复杂的逻辑, 需要用括号来区分
ret = Book.objects.filter((Q(name='红楼梦') & Q(price__gt=100)) | Q(pk__gt=2))
print(ret)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: