确定模型关系:

'''
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. url长度

    今天在测试Email Ticket的时候发现在进行Mark as Read/Unread操作时,请求是通过GET方式进行的.URL中列出了所有参与该操作的Ticket Id.于是,我想起GET请求是有 ...

  2. 在thinkpad SL400上U盘安装双系统ubuntu14.10

    转自:http://zydky.iteye.com/blog/1674100 上文中装的双系统是centos6.3,因为自己对ubuntu有点熟悉,就装了ubuntu. 笔记本是09年入手的,买了之后 ...

  3. JS的定时到底有多不准

    博客逐步迁移到,独立博客,原文地址,http://www.woniubi.cn/js_hide_tab_setinterval/ 我们一直都在说,JS的定时非常的不准确,但是很少有人去验证他,今天我就 ...

  4. ArcGIS Engine中的Symbols详解(转)

    本文来源:http://blog.csdn.net/mengdong_zy/article/details/8980842 原文如下: Symbols Symbol level drawing Joi ...

  5. DirectX HLSL 内置函数

    Intrinsic Functions (DirectX HLSL) The following table lists the intrinsic functions available in HL ...

  6. Web前端开发规范(二)

    3.HTML代码规范 .html文件必须存放在项目工程约定的目录中. .html文件的命名:以模块 + 功能的结合方式来命名,比如:newsList.html. 文档类型声明:HTML4中使用< ...

  7. pure-ftp 修改用户信息

    1.修改用户test的密码 [root@localhost bin]# ./pure-pw passwd test #修改密码 Password: Enter it again: [root@loca ...

  8. 如何让.NET Core应用的配置与源文件保持同步?

    配置的同步涉及到两个方面:第一,对原始的配置文件实施监控并在其发生变化之后从新加载配置;第二,配置重新加载之后及时通知应用程序进而使后者能够使用最新的配置.接下来我们利用一个简单的.NET Core控 ...

  9. mongdb增加字段和删除字段

    增加字段 db.xxx.update({},{"$set":{"column1":1,"column2":0}},false,true); ...

  10. c++中explicit关键字用法

    C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢? 如果c++类 ...