Django之模型层-多表操作

多表操作

数据库表关系

  1. 一对多:两个表之间的关系一旦确定为一对多,必须在数据多的表中创建关联字段
  2. 多对多:两个表之间的关系一定确定为多对多,必须创建第三张表(关联表)
  3. 一对一:一旦两个表之间的关系确定为一对一,在两种表中任意一张表中建立关联字段unique

ORM生成关联表模型

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    # 出版社信息
    # 一对多
    publish = models.ForeignKey(to=‘Publish‘,to_field=‘id‘,on_delete=models.CASCADE)

    # 多对多
    author = models.ManyToManyField(to=‘Author‘)
    def __str__(self):
        return self.title

class Publish(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    email = models.EmailField()

class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()

    # 一对一
    authorDetails = models.OneToOneField(to=‘AuthorDetails‘,to_field=‘id‘,on_delete=models.CASCADE)
    def __str__(self):
        return self.name

class AuthorDetails(models.Model):
    id = models.AutoField(primary_key=True)
    city = models.CharField(max_length=32)
    phone = models.IntegerField()

  • 创建表关系方法:

    • 一对一:OneToOneField()
    • 一对多:ForeignKey()
    • 多对多:ManyToManyField()
  • 表关系模型创建注意事项
    • 创建关联表时不需要在关联字段后面加_id,ORM会自动加
    • 关联表关系:一对多关系

      to=表的时候可以加引号也可以不加,不加引号的话必须被关联的表在关联表上面,to_field也可以不写主键,不写的话默认是关联表的主键

    • on_delete=models.CASCADE在一对多的时候必须要加,一对多的时候也必须要加,如果不加会报on_delete错误
    • null = True 允许关联字段为空
    • 在生成表关系多对多的时候,会另外生成第三张表,不会在该表内生成

多表操作之添加记录

添加记录时先添加单表的记录(不关联其他表的表),插入时与单表插入一样。然后插入与其他表关联了的表的记录,有两种插入方式:

方式1:直接传入一个关联的键

Books.objects.create(b_name=‘红楼梦‘,price=100,author_id=1,publish_id=2)

方式2:传入一个模型对象

publish_obj = Publish.objects.filter(id=‘1‘)[0]
Books.objects.create(b_name=‘红楼梦‘,price=100,author_id=1,publish=publish_obj)

在使用关联字段的时候,可以使用字段名_id,也可以直接使用字段名,使用字段名是打印的一个模型对象,使用字段名_id的话打印的是一个关联的键

book_obj = Books.objects.filter(bid=1)[0]
print(book_obj.b_name)
print(book_obj.publish) #Publish object (2)
print(book_obj.publish.p_name) #南京出版社
print(book_obj.publish_id) # 2

绑定多对多关系

book = Publish.objects.filter(id__gt=2).delete()
cao = Author.objects.get(name=‘曹雪芹‘)
luo = Author.objects.get(name=‘罗贯中‘)
book.author.add(cao,luo)

解除多对多的关系,先找到需要解除的对象

# 参数可以是一个主键也可以是模型对象
book.author.remove(1)

清空多对多关系

book.author.clear()

获取一个模型所有的关联对象

print(book.author.all())

设置多对多关系

# set函数相当于是先清空了(clear)数据,然后再重新赋值,赋值参数是一个可迭代对象
book.author.set(列表)

跨表查询

正向查询:假设关联属性在A表中,通过A查询B对象就是属于正向查询,正向查询按字段

反向查询:假设关联属性在A表中,通过B查询A对象就是属于正向查询,反向查询按表名小写_set

基于对象查询(子查询)

  • 一对多的查询
# 一对多的正向查询:查询红楼梦这本书的出版社名字
book = Book.objects.filter(title=‘红楼梦‘)[0]
print(book.publish.name)

# 一对多的反向查询:查某个出版社出版过的书籍
publish_obj = Publish.objects.get(name=‘南京出版社‘)
ret = publish_obj.book_set.all()
print(ret)
  • 多对多的查询
# 多对多的正向查询:查询红楼梦这本书所有作者的名字
book = Book.objects.filter(title=‘红楼梦‘)[0]
ret = book.author.all()
print(ret)
# 多对多的反向查询:查询曹雪芹写过的书
author = Author.objects.filter(name=‘曹雪芹‘)[0]
ret = author.book_set.all()
print(ret)
  • 一对一的查询
    # 一对一的正向查询:查询名字为曹雪芹的所在城市
    auth = Author.objects.filter(name=‘曹雪芹‘).first()
    print(auth.authorDetails.city)

    # 一对一的反向查询:查询在江苏的作者的名字
    ad = AuthorDetails.objects.filter(city=‘江苏‘).first()
    print(ad.author.name)

基于双下划线的跨表查询(join查询)

正向查询按字段,反向查询按表名小写

双下划线就相当于需要关联哪一张表,相当于sql语句中的join

一对多

# 一对多的正向查询查询红楼梦的出版社名字
# 方式1
ret = Book.objects.filter(title=‘红楼梦‘).values(‘publish__name‘)
print(ret)
# 方式2
ret = Publish.objects.filter(book__title=‘红楼梦‘).values(‘name‘)

多对多

 # 查询红楼梦的作者的名字
 # 方式1
ret = Book.objects.filter(title=‘红楼梦‘).values(‘author__name‘)
print(ret)
 # 方式2
 ret = Author.objects.filter(book__title=‘红楼梦‘).values(‘name‘)

一对一查询

# 查询曹雪芹所在的城市
# 正向查询
ret = Author.objects.filter(name=‘曹雪芹‘).values(‘authorDetails__city‘)
# 反向查询
ret = AuthorDetails.objects.filter(author__name=‘曹雪芹‘).values(‘city‘)
# print(ret)

连续跨表查询

# 手机号以15开头的作者出版过的书籍以及出版社的名称
# 正向查询
ret = Book.objects.filter(author__authorDetails__phone__startswith=151).values(‘title‘,‘publish__name‘)
# 反向查询
ret = Author.objects.filter(authorDetails__phone__startswith=‘151‘).values(‘book__title‘,‘book__publish__name‘)
print(ret)

聚合查询

aggregate()函数

# 查询所有书籍的平均价格
# 聚合查询:聚合函数aggregate
from django.db.models import Avg,Max,Min,Count,Sum
ret = Book.objects.all().aggregate(Avg(‘price‘)) #返回值是一个字典
print(ret)

分组查询

annotate()

单表分组

单表分组查询的ORM语法:单表模型.objects.values(‘group by字段‘).annotate(聚合函数("统计字段")

from django.db.models import Avg,Max,Min,Count,Sum
ret = Emp.objects.values(‘dep‘).annotate(avg_salary=Avg(‘salary‘))
print(ret)

多表分组查询

多表查询分组语句模型:

每一个后表模型.objects.value(‘主键‘).anntota(聚合函数(关联表__ 字段)).values(‘表模型字段以及所有统计字段‘)

 # 查询出版社名称以及出版社出版的书籍数量
# 方式1
ret = Publish.objects.values(‘name‘).annotate(count=Count(‘book__title‘))
print(ret)
# 方式2
ret = Publish.objects.values(‘id‘).annotate(count=Count(‘book__title‘)).values(‘name‘,‘count‘)
print(ret)

# 查询每一个作者出版过的书籍的最高价格
ret = Author.objects.values(‘id‘).annotate(max_price = Max(‘book__price‘)).values(‘name‘,‘max_price‘)
print(ret)

F 与 Q查询

  • F查询

用于在一张表内两个字段进行比较查询,F对象内放的是同一张表的字段,对表进行批量操作也可以使用该类

from django.db.models import F
# 查询评论数大于阅读数
ret = Book.objects.filter(comment_num__gt=F("reda_num"))

# 所有书籍的价格加10
Book.objects.all().update(price=F(‘price‘)+10)
  • Q查询

filter()等方法中的关键字参数查询都是一起进行‘AND‘的,如果需要执行更复杂的查询,可以使用Q对象

Q对象可以使用&、|、~操作符组合起来使用并且可以使用括号进行分组编写任意复杂的Q对象

查询名字是红楼梦的书籍或者价格大于20元的书籍
from django.db.models import F,Q
ret = Book.objects.filter(read_num__gt=F(‘comment_num‘))
print(ret)
ret = Book.objects.filter(Q(title=‘红楼梦‘)|Q(price__gt=20))
print(ret)

原文地址:https://www.cnblogs.com/wualin/p/10115983.html

时间: 2024-07-31 13:25:26

Django之模型层-多表操作的相关文章

模型层单表操作

模型层单表操作 单表操作 例: 1. 单表的查询 1. 单表查询所有用户:models.Book.objects.all() 得到的是 queryset对象(当成列表),列表里面,一个一个的对象[user1,user2] ? 2. render(request, 'booklist.html', {'book_list': ret}) ? 3. 模板里: {% for user in book_list %} #要循环的内容 {{book.name}} {% endfor%} 4. get请求携

Django-5.2 模型层 多表操作

7.3 多表操作 一.创建模型 实例:我们来假定下面这些概念,字段和关系作者模型:一个作者有姓名和年龄.作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系(one-to-one)出版商模型:出版商有名称,所在城市以及email.书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联

Django框架(模型层:单表查询)

创建表 1.创建模型 创建名为book的app,在book下的models.py中创建模型 from django.db import models # Create your models here. class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=64) pub_data = models.DateField() price = model

Django之模型层第二篇:多表操作

Django之模型层第二篇:多表操作 一 表关系回顾 ? 在讲解MySQL时,我们提到,把应用程序的所有数据都放在一张表里是极不合理的. ? 比如我们开发一个员工管理系统,在数据库里只创建一张员工信息表,该表有四个字段:工号.姓名.部门名.部门职能描述,此时若公司有1万名员工,但只有3个部门,因为每一名员工后都需要跟着部门信息(部门名.部门职能),所以将会导致部门信息出现大量重复.浪费空间. ? 解决方法就是将数据存放于不同的表中,然后基于foreign key建立表之间的关联关系. ? 细说的

Django模型层之更多操作

Django模型层之更多操作 一 .ORM字段 1.1 常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. IntegerField 一个整数类型,范围在-2147483648 to 2147483647. CharField 字符类型,必须提供max_length参数, max_length表示字符长度. DateField 日期字段,日期格式 YYYY-MM-DD,相当于Python中的d

Django框架-模型层

Django框架-模型层 一.单表查询之必知必会13条 1.时间字段中的两个关键性参数 create_time = models.DateField() # 年月日 create_time = models.DateTimeField() # 年月日时分秒 # 两个关键性参数 # auto_now:每次操作数据 都会自动刷新当前操作的时间 # auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段 2.搭建测试环境 在django中,你可以写一个单独测试某

Django框架05 /orm单表操作

目录 Django框架05 /orm单表操作 昨日内容回顾 今日内容 orm单表操作 对象关系映射(object relational mapping) 1.orm介绍 2.增: 3.时间问题 4.删 5.改 6.批量插入 -- bulk_create 7.查询api 8.基于双下划线的模糊查询 -- filter双下划线查询 9.总结 总结1 总结2 Django框架05 /orm单表操作 昨日内容回顾 模板相关 模板继承(母版继承) 1. 创建一个xx.html页面(作为母版,其他页面来继承

Django之模型层&ORM操作

一. 单表查询:  1.在模型层创建模型表: from django.db import models # Create your models here. # 单表查询表 class User(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() register_time = models.DateField()      2.连接MySQL,创建表 (具体操作见https://ww

5.Django|模型层--多表关系

多表操作 一对多Book id title price publish email addr 1 php 100 人民出版社 111 北京 2 python 120 沙河出版社 222 沙河 3 go 110 人民出版社 119 北京 4 java 300 人民出版社 111 北京 Book多 id title price publish_id 1 php 100 1 2 python 120 1 3 go 110 2 4 java 300 1 Publish一 id name email ad