确定模型关系:

'''
Publish ---- Book 多对一:一个出版社对应多本书,在多的那张表添加关联字段
Book ---- Author 多对多:一个书对应多个作者,多个作者对应一本书 会自动创建第三张表
Author ---- AuthorDetail 一对一:一个作者对应一个作者信息 注意:
主键可不加,django会默认添加字段为id的主键
Django2版本会强制要求在Foreignkey添加这条参数,django1版本默认添加
on_delete = models.CASCADE
'''

模型建立如下:

 from django.db import models

 # 作者详情表
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday = models.DateField(verbose_name='生日')
telephone = models.BigIntegerField(verbose_name='手机号')
address = models.CharField(max_length=64) # 出版社表
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32, verbose_name="出版社名称")
city = models.CharField(max_length=32, verbose_name='城市')
email = models.EmailField(verbose_name='邮箱') def __str__(self):
return self.name # 书籍表
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32, verbose_name="书籍名称")
publish_date = models.DateField(verbose_name='出版日期')
price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')
read_num = models.IntegerField(verbose_name='阅读数',default=0)
comment_num = models.IntegerField(verbose_name='评论数',default=0) publish = models.ForeignKey(to='Publish', to_field='nid', verbose_name='出版社',on_delete=models.CASCADE)
author = models.ManyToManyField(to='Author',verbose_name='作者') def __str__(self):
return self.title # 作者表
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32, verbose_name="作者名称")
age = models.IntegerField(verbose_name='作者年龄')
author_detail = models.OneToOneField(to='AuthorDetail', to_field='nid', unique=True,on_delete=models.CASCADE) def __str__(self):
return self.name

会生成五张表:

注意事项:

  • 表的名称:myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称
  • id字段是自动添加的。主键也可以不自己写
  • 对于外键字段。django会在字段名上添加‘_id’来创建数据库的列名
  • 定义好模型之后,要告诉django使用这些模型,就要在settings.py文件中的INSTALL_APPS中设置,添加models.py文件所在应用的app名称
  • 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None

添加表记录:

首先添加一个出版社:

   pub = Publish.objects.create(name='人民出版社',email='123@qq.com',city='北京')

然后就可以为书籍绑定关系:

     ===========================绑定一对多关系===========================
为book表绑定关系: publish --- book
方式1
book_obj = Book.objects.create(title='红楼梦',price=100,publish_date='2018-08-08',publish_id=1)
print(book_obj.title) 方式2
pub_obj = Publish.objects.filter(nid=1).first()
book_obj = Book.objects.create(title='西游记',price=100,publish_date='2018-07-07',publish=pub_obj)
print(book_obj.title)
print(book_obj.publish_id)
print(book_obj.publish) # 与这本书籍关联的出版社对象
print(book_obj.publish.name)
     ===========================绑定多对多关系===========================
book_obj = Book.objects.create(title='金瓶子', price=100, publish_date='2018-07-07', publish_id=1)
alex = Author.objects.get(name='alex')
egon = Author.objects.get(name='egon')
# 绑定多对多关系的API book_obj.author.add(egon,alex)
book_obj.author.add(1,2)
book_obj.author.add(*[1,2,3]) 解除多对多关系
book = Book.objects.filter(title='金瓶子').first()
book.author.remove(2)
# 清除所有
book.author.clear()
# 获取所有
# 查询主键为4的数据所有作者的名字
print(book.author.all()) # <QuerySet [<Author: alex>]>
print(book.author.all().values('name','age')) # <QuerySet [{'name': 'alex', 'age': 33}]>

跨表查询:

  1. 基于对象查询
  2. 基于双下划线查询
  3. 聚合和分组查询
  4. F 和 Q查询
      ------------------------------------1、基于对象查询(子查询)------------------------------------

      一对多的正向查询:查询金瓶子这本书的出版社的名字
book_obj = Book.objects.filter(title='金瓶子').first()
print(book_obj.publish) # 与这本书关联的出版社对象
print(book_obj.publish.name) 一对多的反向查询:查询人民出版社出版的书
publish = Publish.objects.filter(name='人民出版社').first()
ret = publish.book_set.all()
print(ret) 多对多的正向查询:查询金瓶子这本书的所有作者名字
book.author.all() 多对多的反向查询:查询alex写的所有的书
author = Author.objects.filter(name='alex').first()
ret = author.book_set.all() 一对一的正向查询:查询egon的作者信息
author = Author.objects.filter(name='egon').first()
ret = author.author_detail.telephone 一对一的反向查询:查询手机号为110的作者的名字和年龄
detail = AuthorDetail.objects.filter(telephone='').first()
ret = detail.author
print(ret.name,ret.age) # alex 33
'''
A--B
关联属性在A表中
正向查询: A--B
反向查询: B--A # 一对多查询
正向查询:按字段
反向查询:按表名(小写)_set.all() # 多对多查询
正向查询:按字段
反向查询:按表名(小写)_set.all() # 一对一查询
正向查询:按字段
反向查询:按表名(小写) 因为一对一查询的只有单条,所以没有all set
'''
     # ------------------------------------2、基于双下划线的跨表查询(join查询)------------------------------------
# 一对多:查询金瓶子这本书的出版社的名字 # 方式1:正向查询:
# ret= Book.objects.filter(title='金瓶子').values('publish__name')
# print(ret) # <QuerySet [{'publish__name': '人民出版社'}]> # 方式2:反向查询:
# Publish.objects.filter(book__title='金瓶子').values('name') # 多对多:查询西游记这本书的所有作者名字 # 正向:按字段
# ret = Book.objects.filter(title='西游记').values('author__name')
# print(ret) # 反向:按表名
# ret = Author.objects.filter(book__title='西游记').values('name')
# print(ret) # 一对一查询 :查询alex的手机号 # 正向
# ret = Author.objects.filter(name='alex').values('author_detail__telephone')
# print(ret) # <QuerySet [{'author_detail__telephone': 110}]> # 反向
# ret1 = AuthorDetail.objects.filter(author__name='alex').values('telephone')
# print(ret1) # <QuerySet [{'telephone': 110}]> # 查询手机号以110开头的作者出版过的所有书籍名称以及书籍出版社名称 # 正向
# ret3 = Book.objects.filter(author__author_detail__telephone__startswith='110').values('title', 'publish__name')
# print(ret3) # <QuerySet [{'title': '西游记', 'publish__name': '人民出版社'}, {'title': '金瓶子', 'publish__name': '人民出版社'}]> # 反向
# ret4 = Author.objects.filter(author_detail__telephone__startswith='110').values('book__title',
# 'book__publish__name')
# print(ret4) # <QuerySet [{'book__title': '金瓶子', 'book__publish__name': '人民出版社'}, {'book__title': '西游记', 'book__publish__name': '人民出版社'}]>
     # ------------------------------------3、聚合查询aggregate:返回的是一个字典,不再是queryset集合------------------------------------
from django.db.models import Avg, Max, Min, Count
# 查询所有书籍的平均价格
# ret = Book.objects.all().aggregate(Avg('price'))
# ret1 = Book.objects.all().aggregate(price=Avg('price'),max_price=Max('price'))
# print(ret) # {'price__avg': 97.0}
# print(ret1) # {'price': 97.0, 'max_price': 100.0}
 1     # ------------------------------------3、分组查询 annotate 返回值依然是queryset------------------------------------
# 单表分组查询:在单表下,按照主键分组没有任何意义 # 查询每一个部门的名称及员工的平均薪水
# select dep,Avg(salary) from emp group by dep
# ret = Emp.objects.values('dep').annotate(avg_salary=Avg('salary'))
# print(ret) # <QuerySet [{'dep': '销售部', 'avg_salary': 2000.0}, {'dep': '技术部', 'avg_salary': 3500.0}, {'dep': '人事部', 'avg_salary': 9000.0}]> # 查询每一个省份的名称及员工数 # ret1 = Emp.objects.values('province').annotate(emp_count=Count('id'))
# print(ret1) # <QuerySet [{'province': '江西', 'emp_count': 2}, {'province': '北京', 'emp_count': 1}, {'province': '南昌', 'emp_count': 1}]> # 查询每一个出版社的名字及出版的书的个数
# ret = Publish.objects.values('name').annotate(Count('book'))
# print(ret) # <QuerySet [{'name': '人民出版社', 'book__count': 3}, {'name': '南京出版社', 'book__count': 1}]> # ret1 = Book.objects.values('publish__name').annotate(Count('nid'))
# print(ret1) # <QuerySet [{'publish__name': '人民出版社', 'nid__count': 3}, {'publish__name': '南京出版社', 'nid__count': 1}]> # ret2 = Publish.objects.values('nid').annotate(c=Count('book__title')).values('name','c')
# print(ret2) # 查询每个作者的名字及出版过的书籍的最高价格
# ret3 = Author.objects.values('nid').annotate(m=Max('book__price')).values('name','m')
# print(ret3) # 总结跨表的分组查询的模型
# 每一个表的模型.objects.values('pk').annotate(聚合函数(关联表__字段)).values所有字段)
# 每一个表的模型.objects.annotate(聚合函数(关联表__字段)).values(所有字段) # 查询每一个书籍的名称对应的作者个数
# ret4 = Book.objects.values('pk').annotate(c=Count('author__name')).values('title','c')
# print(ret4) # 统计每一本以py开头的书籍的作者个数:
# ret5 = Book.objects.filter(title__startswith='py').annotate(c=Count('author__name')).values('title','c')
# print(ret5) # 统计不止一个作者的书籍
# ret6 = Book.objects.values('pk').annotate(c=Count('author__name')).filter(c__gt=1).values('title','c')
# print(ret6)

总结跨表的分组查询模型:

 每一个表的模型.objects.values('pk').annotate(聚合函数('关联表__字段').values('字段1',‘字段2’))

 每一个表的模型.objects.annotate(聚合函数(关联表__字段)).values(所有字段)

练习:

     # 查询每一个书籍的名称对应的作者个数

     # ret4 = Book.objects.values('pk').annotate(c=Count('author__name')).values('title','c')
# print(ret4) # 统计每一本以py开头的书籍的作者个数:
# ret5 = Book.objects.filter(title__startswith='py').annotate(c=Count('author__name')).values('title','c')
# print(ret5) # 统计不止一个作者的书籍
# ret6 = Book.objects.values('pk').annotate(c=Count('author__name')).filter(c__gt=1).values('title','c')
# print(ret6)
     # ------------------------------------F和Q查询------------------------------------
from django.db.models import F,Q # 查询评论数大于阅读数的
# ret = Book.objects.filter(read_num__gt=F('comment_num'))
# print(ret) # 所有书籍的价格+10
# ret = Book.objects.all().update(price=F('price')+1)
# print(ret) # 复杂的条件查询 # 查询书籍名称是红楼梦 且 价格是78的书籍
ret = Book.objects.filter(Q(title='红楼梦')&Q(price=78))
# 查询书籍名称是红楼梦 或 价格是78的书籍
Book.objects.filter(Q(title='红楼梦')|Q(price=78))
# 取反 非的意思 名称不是红楼梦或者价格等于78
Book.objects.filter(~Q(title='红楼梦')|Q(price=78))
print(ret)

010---Django的模型层(2)的更多相关文章

  1. 64、django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  2. 67、django之模型层(model)--查询补充及mookie

    本篇导航: F查询与Q查询 cookie 一.F查询与Q查询 1.以Book表为例 class Book(models.Model) : title = models.CharField(max_le ...

  3. 【Django】模型层说明

    [Django模型层] 之前大概介绍Django的文章居然写了两篇..这篇是重点关注了Django的模型层来进行学习. ■ 模型定义 众所周知,Django中的模型定义就是定义一个类,其基本结构是这样 ...

  4. django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  5. django之模型层(model)--查询补充及cookie

    已经连续写了好几篇django的模型层(model)增删改查的随笔了,没篇大篇幅都是查询相关的操作,可以看出查询在数据的操作中是多么的重要,而本篇最后再补充一点关于关于查询的一些方法,模型层基本的操作 ...

  6. python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)

    昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...

  7. Django基础(2)--模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介

    没整理完 昨日回顾: 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 ...

  8. Django之模型层(2)

    Django之模型层(2) 一.创建模型 实例:我们来假定下面这些概念,字段和关系. 作者模型:一个作者由姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情 ...

  9. 第五章、Django之模型层----多表查询

    目录 第五章.Django之模型层----多表查询 一.一对多字段增删改查 1.增 2.查 3.改 4. 删除 二.多对多的增删改查 1. 增 2. 改 3. 删 三.ORM跨表查询 四.正反向的概念 ...

  10. 第五章、Django之模型层---单表操作

    目录 第五章.Django之模型层---单表操作 一.ORM查询 二.Django测试环境搭建 三.单表查询 1. 增 2. 改 3. 删 4. 查 第五章.Django之模型层---单表操作 一.O ...

随机推荐

  1. Gremlin--一种支持对图表操作的语言

    Gremlin 是操作图表的一个非常有用的图灵完备的编程语言.它是一种Java DSL语言,对图表进行查询.分析和操作时使用了大量的XPath. Gremlin可用于创建多关系图表.因为图表.顶点和边 ...

  2. iphone 微信下浏览器中数字去除下划线

    在开发iphone应用程序的时候,safari下手机号码默认是有下划线的,通过下面的方法就可以去掉: <meta name="format-detection" conten ...

  3. staticmethod classmethod property方法

    @staticmethod 静态方法 函数修饰符,用来修饰一个函数,类似于装饰器 class Dog(object): def __init__(self,name): self.name = nam ...

  4. [SVN]TortoiseSVN工具培训1─为什么要用SVN?

    你是否有经历过以下情况: SVN的使用理由/好处:

  5. SharePoint 2010 列表查阅项栏的formfield控件对象取值

    开发的时候想当然的认为主表解析出来就是一个dropdownlist,可是在大数据测试的时候,发现有情况. 首先创建一个子列表:DetailList,并添加19条数据: 创建主列表:MainList,并 ...

  6. 关于 supersocket 不能通过Bootstrap 启动

    App.config内容   <configSections> <section name="superSocket" type="SuperSocke ...

  7. 洛谷 P2251 质量检测

    题目背景 无 题目描述 为了检测生产流水线上总共N件产品的质量,我们首先给每一件产品打一个分数A表示其品质,然后统计前M件产品中质量最差的产品的分值Q[m] = min{A1, A2, ... Am} ...

  8. C盘压缩,电脑无法正常启动的解决方法?

    有时候,我们觉得电脑很卡,因此压缩磁盘来节约资源,前段时间,由于不小心将C盘压缩了,导致电脑无法正常启动,查了一些有关的资料,发现很多人都遇到过类似的问题,如果你不想重装系统的话,那么,现在我说一下我 ...

  9. Jmeter入门5 关联 响应数据传递-正则表达式提取器

    在测试过程中,遇到一个问题:用户登录成功后服务器会返回一个登录凭证,之后所有的操作都需要带上此凭证.我们怎么获取登录凭证并传递给后续的操作? Jmeter提供了正则表达式提取器,用变量提取参数,后续通 ...

  10. IOS 制作常用代码的快捷方式

    输入可以变的对象或类型,要用<#name#>