Django 模型层(2)

多表操作---模型之间的关系

1 一对一:作者----作者详细信息

2 一对多:书籍----出版社

3 多对多:书籍----作者

一  创建模型(主键(id)自动创建)

没有任何关系的一张表的创建

class Emp(models.Model):
name=models.CharField(max_length=32)
age=models.IntegerField()
salary=models.DecimalField(max_digits=8,decimal_places=2)
dep=models.CharField(max_length=32)
province=models.CharField(max_length=32)

单独一张表对应的模型类

1 一对一 OneToOneField

models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)
参数to:表示与AuthorDetail绑定一对一关系
参数 null=True:表示允许为空;
参数on_delete:级联删除,表示当一对一关系的一方数据被删除了,其对应关系也删除了
class Author(models.Model):
'''
...其他字段省去
'''
# 作者与authordetail建立一对一关系
authordetail=models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)

2一对多 ForeignKey (在多的一方(Book)绑定)

 基本书写格式:
   ForeignKey(to='被关联的表名’,null=True,on_delete=models.CASCADE)
class Book(models.Model):
'''
。。。
'''
# 创建一对多的关系:一个出版社可以对应多本书
publish = models.ForeignKey(to='Publish', null=True, on_delete=models.CASCADE)

3 多对多 ManyToMany

  注意:

    1 自动创建关系表book_author;

 authors = models.ManyToManyField(to='Author')
class Book(models.Model):
'''
...
''' # 书籍与作者创建多对多的关系
authors = models.ManyToManyField(to='Author')
from django.db import models

# Create your models here.

# 关系户:书籍------作者  多对多
# 书籍------出版社 一对多
# 作者------作者详细信息 一对一 class Book(models.Model):
'''
创建书籍表
'''
title = models.CharField(max_length=32)
pub_date = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2) # 创建一对多的关系:一个出版社可以对应多本书
publish = models.ForeignKey(to='Publish', null=True, on_delete=models.CASCADE) # 书籍与作者创建多对多的关系
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.title class Publish(models.Model):
'''
创建出版社表
'''
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name class Author(models.Model):
'''
创建作者表
'''
name=models.CharField(max_length=32)
age=models.IntegerField() # 作者与authordetail建立一对一关系
authordetail=models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)
def __str__(self):
return self.name class AuthorDetail(models.Model):
'''
创建作者详细信息表
'''
birthday=models.DateField()
telephone=models.BigIntegerField()
addr=models.CharField(max_length=64)
def __str__(self):
return self.addr

创建表模型类的完整代码

4 数据迁移

方法一

python manage.py makemigrations

python manage.py migrate

数据迁移代码

方法二

pycharm 中快捷启动方式

5 创建的表结果

二 添加记录

单表添加数据的两种基本方式

models.AuthorDetail(id=1,birthday="1995-12-12",telephone=110,addr="北京")

方式一(类的是实例化)

obj=models.AuthorDetail.objects.create(birthday="1995-12-12",telephone=110,addr="北京")  

方式二(模型类objects管理器下的create方法)

1 一对一

 # 添加一对一关系记录方式一
models.Author.objects.create(name='alex',age='',authordetail_id=1) # 添加一对一关系记录方式二
wusir_d = models.AuthorDetail.objects.create(birthday="1999-8-12", telephone=666, addr="上海")
wusir=models.Author.objects.create(name='wusir',age=18,authordetail=wusir_d) #接收记录对象

2 一对多

# 绑定方式一
python=models.Book.objects.create(title='python',pub_date='2015-10-8',price=120,publish_id=1)
# 绑定方式二
strawberry=models.Publish.objects.create(name='草莓出版社',city='武汉',email='999@eee')
go=models.Book.objects.create(title='go',pub_date='2014-12-9',price=150,publish=strawberry)

3 多对多(如何给关系表添加数据)

正向:找关联属性

 # 正向绑定用字段  书籍找关系表通过Author属性
python=models.Book.objects.filter(title='python').first()
go=models.Book.objects.filter(title='go').first() alex=models.Author.objects.filter(name='alex').first()
egon=models.Author.objects.filter(name='egon').first()
print(python,alex,egon)
print(python.publish.city)

给python书籍绑定两个作者信息

反向:表名小写

    linux = models.Book.objects.filter(title="linux").first()
R = models.Book.objects.filter(title="R").first()
wusir = models.Author.objects.filter(name="wusir").first() wusir.book_set.add(linux,R)

给egon绑定两本书

给关联表添加记录的方法

#以python书籍对象为例
python.authors.remove(alex)#移除作者信息 alex python.authors.clear() #清空作者信息 python.authors.add(作者对象1,作者对象2) #添加作者信息 python.authors.add(1,2) #添加作者信息 python.authors.set([ 1,]) #先清空后设置值

关联表的方法

二 基于对象的跨表查询 ********

方法总结
正向查询:按照关系字段
对象1 -----------------------------------------> 对象2
<----------------------------------------
反向查询:按照表名小写_set.all()
是否需要_set取决于结果的个数,
多个结果加_set.all()

1 一对一

 # 正向制作者--->作者详细信息
#alex---->电话号码
# alex=models.Author.objects.filter(name='alex').first()
# result=alex.authordetail.telephone

正向查询

    # 反向查询作者<----作者详细信息
#tel=110的作者是谁
# ad=models.AuthorDetail.objects.filter(telephone=110).first()
# result=ad.author.name

反向查询

2 一对多

 # 查询linux这本书籍的出版社信息地址(正向查询)
linux=models.Book.objects.filter(title='linux').first()
result=linux.publish.city

正向查询

    # 反向查询(出版社--->书籍)
# 查询橘子出版社出版过的所有书籍
publish=models.Publish.objects.filter(name='橘子出版社').first()
print(publish)
result=publish.book_set.all()
print(result) #<QuerySet [<Book: java>]>
for i in result:
print(i.title)

反向查询

3 多对多

正向查询
反向查询

三 基于双下划线的跨表查询

模型类.objects.filter().values()

1 跨表操作在filter 和values使用__(双下划线)进行跨表操作;
2 正向查询按关联字段,反向查询按照表名小写;

  1 一对一

    # 查询alex的手机号

    # 正向查询
ret=Author.objects.filter(name="alex").values("authordetail__telephone") # 反向查询
ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")

  2 一对多

# 练习:  查询苹果出版社出版过的所有书籍的名字与价格(一对多)

    # 正向查询 按字段:publish

    queryResult=Book.objects
            .filter(publish__name="苹果出版社")
            .values_list("title","price") # 反向查询 按表名:book queryResult=Publish.objects
              .filter(name="苹果出版社")
              .values_list("book__title","book__price")

  3 多对多

# 练习: 查询alex出过的所有书籍的名字(多对多)

    # 正向查询 按字段:authors:
queryResult=Book.objects
            .filter(authors__name="yuan")
            .values_list("title") # 反向查询 按表名:book
queryResult=Author.objects
              .filter(name="yuan")
              .values_list("book__title","book__price")

  4 进阶练习(连续跨表)

# 练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名

    # 正向查询
queryResult=Book.objects
            .filter(publish__name="人民出版社")
            .values_list("title","authors__name")
# 反向查询
queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("book__title","book__authors__age","book__authors__name") # 练习: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称 # 方式1:
queryResult=Book.objects
            .filter(authors__authorDetail__telephone__regex="")
            .values_list("title","publish__name")
# 方式2:
ret=Author.objects
.filter(authordetail__telephone__startswith="")
.values("book__title","book__publish__name")

双下划线跨表跨表巩固

四 聚合查询于分组

emp-dep:

id  name age   salary   dep_id   id   name
1 alex 12 2000 1 1 销售部
2 egon 22 3000 2 2 人事部
3 wen 22 5000 2 2 人事部 class Emp(models.Model):
name=models.CharField(max_length=32)
age=models.IntegerField()
salary=models.DecimalField(max_digits=8,decimal_places=2)
dep=models.CharField(max_length=32)
province=models.CharField(max_length=32)

  1 聚合 (aggregate) ---聚合函数 Sav, Max, Min, Avag

基本语法:
模型类.objects.aggregate(聚合函数( 字段 ))
结果:queryset类型,一个对象一个字典保存数据
实例1:
# 计算所有图书的平均价格
from django.db.models import Avg
Book.objects.all().aggregate(Avg('price')) # {'price__avg': 34.35}
实例2:
from django.db.models import Avg, Max, Min
Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
#{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

  2 分组(annotate)

key:
跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。 
语法格式:
(1)模型类.objects.all().value('分组条件').annotate('聚合函数')
结果是queryset对象,其中元素是字典
<QuerySet [{..},{...}]> (2)模型类.objects.all().annotate('聚合函数') #以主键分组
结果是queryset对象,其中元素是对象
#<QuerySet [<Book: java>,<Book: java>]>

  3 练习

(1)统计每个出版社的最便宜的书

publish_list=models.Publish.objects.annotate(min("book_price"))

for publish_obj in publish_list:
print(publish_obj.name,publish_obj.MinPrice)
简化代码:
queryResult= Publish.objects
            .annotate(MinPrice=Min("book__price"))
            .values_list("name","MinPrice")
print(queryResult)
SELECT "app01_publish"."name", MIN("app01_book"."price")  AS "MinPrice" FROM "app01_publish"
LEFT JOIN "app01_book" ON ("app01_publish"."nid" = "app01_book"."publish_id")
GROUP BY "app01_publish"."nid", "app01_publish"."name", "app01_publish"."city", "app01_publish"."email"

对应mysql语句

(2)统计每本书的作者个数

models.Book.objects.annotate(authorsNum=Count('authors'))#待会检测

(3)统计每一本以py开头的书籍的作者个数

models.Book.objects.filter(title_startswith='py')
            .annocate(num_authors=Count('authors')
            .values('title','c')

(4)统计不止一个作者的图书

models.Book.objects
.annocate( num_authors=Count('author'))
.filter(num_authors__lg=1)

(5)根据一本图书作者数量的多少对查询集 QuerySet进行排序

models.Book.objects
.annotate(num_authors=Count('authors'))
.order_by('num_authors')

(6)查询各个作者出的书的总价格

models.author.objects
.annotate(sum_price=sum('book__price'))
.values('name','sum_price')

五 F查询与Q 查询

  1 F查询 ---- F('字段名')

(1) 意义

1 在过滤条件中借助F查询,使得字段之间可以作比较;
2 在过滤条件中借助F查询,使得字段之间可以做四则运算;

(2) 字段之间的比较实例

# 查询评论数大于收藏数的书籍

from django.db.models import F

models.objects.filter(commentNum__lg=F('keepNum'))

(3) 四则运算在过滤条件中的应用

# 查询评论数大于收藏数2倍的书籍

from django.db.models import F
models.Book.objects.filter(commerntNum__lg=F('keepNum')*2) #修改操作也可以使用F函数,比如将每一本书的价格提高30元: models.Book.objects.update(price=F('price)+30)

  2 Q 查询 ---- Q('字段名')

(1)  意义

使得过滤条件的方式不再是单一的 & (与)运算

Q查询中的与|或|非
与: &
或: |
非: ~

(2)查询价格大于300或者名称以p开头的书籍 ( |  或运算)

queryset=models.Book.objects.filter(price__lg=300|Q(title__startswith='p')).values('title')

(3)查询价格大于300或者不是2019年一月份的书籍

models.Book.objects.filter(title__lg=300|~Q(Q(pub_date_year=2016)&Q(pub_date_mouth=1)))

django 模型层(2)的更多相关文章

  1. Django模型层(2)

    <!DOCTYPE html><html lang="zh-cn"><head><meta charset="utf-8&quo ...

  2. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  3. Django模型层之ORM

    Django模型层之ORM操作 一 ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...

  4. Django模型层之单表操作

    Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...

  5. Django模型层之更多操作

    Django模型层之更多操作 一 .ORM字段 1.1 常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为 ...

  6. Django模型层(各种表及表数据的操作)

    目录 一.Django模型层 0. django模型层的级联关系 1. 配置django测试脚本 (1)方式一 (2)方式二 2. orm表数据的两种增删改 (1)方式一: (2)方式二: 3. pk ...

  7. day 70 Django基础五之django模型层(二)多表操作

    Django基础五之django模型层(二)多表操作   本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...

  8. day 69 Django基础五之django模型层(一)单表操作

    Django基础五之django模型层(一)单表操作   本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现 ...

  9. day 57 Django基础五之django模型层之关联管理器

    Django基础五之django模型层之关联管理器   class RelatedManager "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器.它存在于下面两种情况 ...

随机推荐

  1. asp.net core系列 26 EF模型配置(实体关系)

    一.概述 EF实体关系定义了两个实体互相关联起来(主体实体和依赖实体的关系,对应数据库中主表和子表关系). 在关系型数据库中,这种表示是通过外键约束来体现.本篇主要讲一对多的关系.先了解下描述关系的术 ...

  2. HashMap,HashTable,ConcurrentHashMap异同比较

    0. 前言 HashMap和HashTable的区别一种比较简单的回答是: (1)HashMap是非线程安全的,HashTable是线程安全的. (2)HashMap的键和值都允许有null存在,而H ...

  3. Apache coredump 问题发现与解决记录

    目录 Apache coredump 问题发现与解决记录 背景 发现问题 解决问题 方法 1 方法 2 总结 Linux 程序编译链接动态库版本问题 ldd 命令 动态库的编译和 soname 线上 ...

  4. 聊天框Demo:DotNetCore+ActiveMQ+Mqttjs 实现前后台消息监听

    网上查了查 ActiveMQ + .net core 的例子很少,自己做一个demo 作为记录,另外FineUI Core基础版要来了,出来后我会用FineUI再做一版,为知识星球的引流... 1.安 ...

  5. VisualStudio移动开发(C#、VB.NET)Smobiler开发平台——SliderView控件的使用方式

    SliderView控件 一.          样式一 我们要实现上图中的效果,需要如下的操作: 从工具栏上的“Smobiler Components”拖动一个SliderView控件到窗体界面上 ...

  6. Mybatis框架基础支持层——日志模块(8)

    前言: java开发中常用的日志框架有Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口不尽相同.为了统一这些工具的接 ...

  7. 如何保证MongoDB的安全性?

    上周写了个简短的新闻<MongoDB裸奔,2亿国人求职简历泄漏!>: 根据安全站点HackenProof的报告,由于MongoDB数据库没有采取任何安全保护措施,导致共计202,730,4 ...

  8. Ext.define(override)

    Ext.define(override)作用是:定义类的补丁(扩展或重写) 有3中使用方法,见附件 Ext.define(override).zip

  9. Selenium自动化-调用Mysql数据库

    上几篇博客发布了几篇Selenium入门知识和进阶, 现在附上如何 从数据库中取值 能够逐行取值,并且返回二维数组 import java.io.FileInputStream; import jav ...

  10. css direction 属性简介与实际应用。

    目前正在用vue构建组件库.写到弹框的时候没想到按钮的顺序问题,但是在应用中,确实会有选项按钮顺序不同的情况发生,但是又想共用一个组件.那么问题就出现了.后来看到了这篇文章,才茅塞顿开. direct ...