确定模型关系:

'''
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. 基于Python的开源人脸识别库:离线识别率高达99.38%

    项目地址:https://github.com/ageitgey/face_recognition#face-recognition 本文的模型使用了C++工具箱dlib基于深度学习的最新人脸识别方法 ...

  2. 《深入理解Java 7核心技术与最佳实践》读书笔记(2) Java语言动态性引言

    Java语言是一种静态类型的编程语言.静态类型的含义是指在编译时进行类型检查.Java源代码中的每个变量的类型都要显式地进行声明.所有变量.方法的参数和方法返回值的类型在程序运行之前就必须是已知的.J ...

  3. K星异客

    http://baike.baidu.com/view/222058.htm 这部改编自基恩·布汝尔1995年出版的同名小说的电影在当年的十月档票房榜上称冠.本来这部电影的外星人主人公属意于威尔.史密 ...

  4. 花3分钟了解下C/C++中的函数可变参简单实现

    1.可变参函数的原理 C/C++函数的参数是存放在栈区的,并且参数的入栈是从参数的右边开始,即最后一个参数先入栈,而第一个参数最后才入栈,所以,根据栈的后进先出性质,函数总能找到第一个参数.所以,可变 ...

  5. 【2017-06-20】Linux应用开发工程师C/C++面试问题记录之一:Linux多线程程序的同步问题

    参考之一:Linux 线程同步的三种方法 链接地址:http://www.cnblogs.com/eleclsc/p/5838790.html 简要回答: Linux下线程同步最常用的三种方法就是互斥 ...

  6. 【js基础修炼之路】— 我理解的原型链

    提起原型链,大家并不陌生,但是对于新人来说一提到原型方面的东西就会比较懵.在我自一次面试的时候,面试官也给我提了这样的问题,当时就按照我的理解说了一些,但是很肤浅,在此我希望给刚入门的前端小伙伴聊一下 ...

  7. POJ - 3109 Inner Vertices

    不存在-1的情况,而且最多一轮就结束了.如果新增加的黑点v0会产生新的黑点v1,那么v0和v1肯定是在一条轴上的,而原来这条轴上已经有黑点了. 离散以后扫描线统计,往线段上插点,然后查询区间上点数. ...

  8. Poj(1789),最小生成树,Prim

    题目链接:http://poj.org/problem?id=1789 还是套路. #include <stdio.h> #include <string.h> #define ...

  9. vue中的js动画与Velocity.js结合

    vue里面除了用css写动画,还可以用js写动画,vue的transition中,定义了几个动画钩子 第一个动画钩子:@before-enter <div id='app'> <tr ...

  10. 【转】Android xml资源文件中@、@android:type、@*、?、@+含义和区别

    一.@代表引用资源 1.引用自定义资源.格式:@[package:]type/name android:text="@string/hello" 2.引用系统资源.格式:@andr ...