环境:

django1.9环境:

settings.py,注释csrf,并且设置使用mysql数据库

数据库的对应关系图:

一、多表模型创建,一对多增删改查,多对多增删改查

一对多:

models.py

总结:

#用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id
# ManyToManyField会自动创建第三张表
# *************重点
# 一对一的关系:OneToOneField
# 一对多的关系:ForeignKey
# 多对多的关系:ManyToManyField

# id如果不写,会自动生成,名字叫nid,并且自增(数据库类型不同,生成的名字也会随之不同)

from django.db import models# Create your models here.
class Publish(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)addr = models.CharField(max_length=64)email = models.EmailField()class AuthorDetail(models.Model):id = models.AutoField(primary_key=True)phone = models.CharField(max_length=32)addr = models.CharField(max_length=64)class Author(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=16)# 数字类型sex = models.IntegerField()# # to='AuthorDetail'  加引号,这个表能找到就可以,不用引号,类必须在上面定义authordetail = models.OneToOneField(to='AuthorDetail', to_field='id')def __str__(self):return self.nameclass Book(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)price = models.DecimalField(max_digits=5, decimal_places=2)publish = models.ForeignKey(to=Publish, to_field='id')authors = models.ManyToManyField(to=Author)def __str__(self):return self.name

python3 manage makemigrations
python3 manage migrate

二、添加表记录

在11-13数据库中的app01_publish表中添加出版社数据:

在项目的根下添加test.py文件

import os
if __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pro11_13.settings")import djangodjango.setup()from app01.models import *# 以上代码是属于如何让py文件在django环境中运行 # 一对多新增数据# 添加一本北京出版社出版的书# 第一种方式ret=Book.objects.create(name='红楼梦',price=34.5,publish_id=1)print(ret.name)# 红楼梦

然后在book表中就会出先之前插入的数据。

import osif __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pro11_13.settings")import djangodjango.setup()from app01.models import *# 第二种方式,存对象publish=出版社的对象,存到数据库,是一个idpublish=Publish.objects.filter(pk=2).first()ret = Book.objects.create(name='西游记', price=34.5, publish=publish)print(ret.name)# 西游记

一对一修改数据:

方式一:

book=Book.objects.get(pk=1)
book.publish=出版社对象
book.publish_id=2
book.save()

方式二:

book=Book.objects.filter(pk=1).update(publish=出版社对象)
# book=Book.objects.filter(pk=1).update(publish_id=1)

多对多新增:

首先在数据中添加作者与作者详情

# 为红楼梦这本书新增一个叫lqz,egon的作者

方式一:

lqz=Author.objects.filter(name='lqz').first()
egon=Author.objects.filter(name='egon').first()
book=Book.objects.filter(name='红楼梦').first()
# add 添加多个对象
book.authors.add(lqz,egon

方式二:(为了测试,先把app01_book_authors表中的数据全部删除)

book=Book.objects.filter(name='红楼梦').first()
book.authors.add(1,2)

多对多删除:

方式一:

# remove,可以传对象,可以传id,可以传多个,不要混着用

lqz=Author.objects.filter(name='lqz').first()
book=Book.objects.filter(name='红楼梦').first()
book.authors.remove(lqz)

方式二:

lqz=Author.objects.filter(name='lqz').first()
egon=Author.objects.filter(name='egon').first()
book=Book.objects.filter(name='红楼梦').first()
book.authors.remove(1)
# book.authors.remove(1,2)
# clear清空所有
# book.authors.clear()

多对多修改:

#  set,先清空,在新增,要传一个列表,列表内可以是, id,也可以是对象

原来表中的数据:

lqz=Author.objects.filter(name='lqz').first()
egon=Author.objects.filter(name='egon').first()
book=Book.objects.filter(name='红楼梦').first()
book.authors.set([2,])
# 或者:
# book.authors.set([lqz,])

修改之后:

错误方式:

********这样不行,因为它打散了传过去了,相当于book.authors.set(lqz)
# book.authors.set(*[lqz,])

总结:

添加表记录
        1 一对多新增
            -两种方式:
                -publish=对象
                -publish_id=id
        2 一对多删除:同单表删除
        3 一对多修改:两种方式,可以传对象,可以传id
        4 一对一跟一对多一样
        5 多对多:
            -add  ----->可以传对象,可以传id,可以传多个
            -remove  ----->可以传对象,可以传id,可以传多个
            -clear  ---->没有参数
            -set   ----->跟上面不一样,必须传列表,列表里面可以是对象,可以是id

三、基于对象的跨表查询,一对一,一对多,多对多查询

1 一对一
            正向:正向查询按字段,(author---关联字段在author--->authordetail   ------>  按字段)

# 查询egon作者的手机号   正向查询

author=Author.objects.filter(name='egon').first()
authordetail=author.authordetail
print(authordetail.phone)
---------------------------------
13513513561

反向:反向查询按表名小写,(authordetail------关联字段在author--->author  -----> 按表名小写)

#  查询地址是 :山东 的作者名字   反向查询

authordetail=AuthorDetail.objects.filter(addr=' 上海').first()
author = authordetail.author
print(author.name)
----------------------------
egon

2 一对多
            正向:正向查询按字段。(拿书查出版社信息)

正向   book---关联字段在book--->publish   ------>  按字段

正向 查询红楼梦这本书的出版社邮箱

book=Book.objects.filter(name='红楼梦').first()
pulish=book.publish
print(pulish.email)
-------------------
564@qq.com

反向:反向按表名小写_set.all()

反向   publish------关联字段在book--->book  -----> 按表名小写_set.all()(拿出版社信息查询图书)。

反向  查询地址是北京 的出版社出版的图书

publish=Publish.objects.filter(addr='北京').first()
books=publish.book_set.all()  # publish.book_set.all()  拿出所有的图书
print(books)
--------------------
<QuerySet [<Book: 红楼梦>]>
# 统计一下条数
books=publish.book_set.all().count()
print(books)
-----------------
1

3 多对多
            正向:正向查询按字段

正向   book---关联字段在book--->author   ------>  按字段.all()

#查询红楼梦这本书所有的作者

book=Book.objects.filter(name='红楼梦').first()
print(book.authors.all())   # 是所有的作者,是一个queryset对象,可以继续点
---------------------------------------------
<QuerySet [<Author: egon>]>

反向查询:反向按表名小写_set.all()

反向   author------关联字段在book--->book  -----> 按表名小写_set.all()

# 查询lqz写的所有书

egon=Author.objects.filter(name='egon').first()
books=egon.book_set.all()
print(books)
------------------------------------------------------
<QuerySet [<Book: 红楼梦>]>

# 连续跨表
 # 查询红楼梦这本书所有的作者的手机号

book=Book.objects.filter(name='红楼梦').first()
authors=book.authors.all()for author in authors:authordetail=author.authordetailprint(authordetail.phone)
-----------------------------------------
13513513561

四、******基于对象的查询,是子查询也就是多次查询)

*********************基于双下划线的查询***************

# 一对一
# 查询lqz作者的手机号   正向查询  跨表的话,按字段
# 以author表作为基表

ret=Author.objects.filter(name='egon').values('authordetail__phone')
print(ret)
------------------------------
<QuerySet [{'authordetail__phone': '13513513561'}]>

# 以authordetail作为基表

# 反向查询,按表名小写  跨表的话,用表名小写

ret=AuthorDetail.objects.filter(author__name='egon').values('phone')
print(ret)
---------------------------------------------
<QuerySet [{'phone': '13513513561'}]>

# 查询lqz这个作者的性别和手机号
# 正向

ret=Author.objects.filter(name='egon').values('sex','authordetail__phone')
print(ret)
-------------------------
<QuerySet [{'sex': 1, 'authordetail__phone': '13513513561'}]>

# 查询手机号是13513513561的作者性别

ret=Author.objects.filter(authordetail__phone='13513513561').values('sex')
print(ret)
-------------------------------------
<QuerySet [{'sex': 1}]>
ret=AuthorDetail.objects.filter(phone='13513513561').values('author__sex')
print(ret)
-------------------------
<QuerySet [{'author__sex': 1}]>

五、基于双下划线的一对多查询

# 查询出版社为北京出版社出版的所有图书的名字,价格
ret=Publish.objects.filter(name='北京出版社').values('book__name','book__price')
print(ret)
----------------------------------------------------------------------
<QuerySet [{'book__name': '红楼梦', 'book__price': Decimal('34.50')}, {'book__name': '西游记', 'book__price': Decimal('553.30')}]>
------------------------------------------------------------------------
ret=Book.objects.filter(publish__name='北京出版社').values('name','price')
print(ret)
-----------------------------------------------------
<QuerySet [{'name': '红楼梦', 'price': Decimal('34.50')}, {'name': '西游记', 'price': Decimal('553.30')}]># 反向查询
# 查询北京出版社出版的价格大于19的书
ret=Publish.objects.filter(name='北京出版社',book__price__gt=19).values('book__name','book__price')
print(ret)
-----------------------------------------------------
<QuerySet [{'book__name': '红楼梦', 'book__price': Decimal('34.50')}, {'book__name': '西游记', 'book__price': Decimal('553.30')}]>

六、基于双下划线的多对多查询

# 查询红楼梦的所有作者名字
ret=Book.objects.filter(name='红楼梦').values('authors__name')
print(ret)
--------------------------
<QuerySet [{'book__name': '红楼梦', 'book__price': Decimal('34.50')}, {'book__name': '西游记', 'book__price': Decimal('553.30')}]>
-----------------------------------------------------------
ret=Author.objects.filter(book__name='红楼梦').values('name')
print(ret)
------------------------------------------------------------------
<QuerySet [{'name': 'egon'}]>
# 查询图书价格大于30的所有作者名字
ret=Book.objects.filter(price__gt=30).values('authors__name')
print(ret)
---------------------------------
<QuerySet [{'authors__name': 'egon'}, {'authors__name': None}]>
# 进阶练习--连续跨表# 查询北京出版社出版过的所有书籍的名字以及作者的姓名
ret=Publish.objects.filter(name='北京出版社').values('book__name','book__authors__name')
print(ret)
----------------------------------------
<QuerySet [{'book__name': '红楼梦', 'book__authors__name': 'egon'}, {'book__name': '西游记', 'book__authors__name': None}]>
----------------------------------------------------------
ret=Book.objects.filter(publish__name='北京出版社').values('name','authors__name')
print(ret)
---------------------------------------
<QuerySet [{'name': '红楼梦', 'authors__name': 'egon'}, {'name': '西游记', 'authors__name': None}]># 手机号以135开头的作者出版过的所有书籍名称以及出版社名称
ret=AuthorDetail.objects.filter(phone__startswith='135').values('author__book__name','author__book__publish__name')
print(ret)
--------------------------------------------------
<QuerySet [{'author__book__name': '红楼梦', 'author__book__publish__name': '北京出版社'}]>
---------------------------------------------------------------------
ret=Book.objects.filter(authors__authordetail__phone__startswith='135').values('name','publish__name')
print(ret)
-----------------------------------------------------------------------
<QuerySet [{'name': '红楼梦', 'publish__name': '北京出版社'}]>

# 聚合查询aggregate

from django.db.models import Avg,Count,Max,Min,Sum
# 计算所有图书的平均价格
ret=Book.objects.all().aggregate(Avg('price'))
print(ret)
-----------------------
{'price__avg': 293.9}#  计算图书的最高价格
ret=Book.objects.all().aggregate(Max('price'))
print(ret)
------------------------------------
{'price__max': Decimal('553.30')}#他是queryset的终止子句
# 计算图书的最高价格,最低价格,平均价格,总价
ret=Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price'))
print(ret)
---------------------------------------------
{'price__max': Decimal('553.30'), 'price__min': Decimal('34.50'), 'price__avg': 293.9, 'price__sum': Decimal('587.80')}# 分组查询annotate()
# 统计每一本书作者个数
ret=Book.objects.all().annotate(c=Count('authors'))
print(ret)
for r in ret:print(r.name,'---->',r.c)
----------------------------------------------
<QuerySet [<Book: 红楼梦>, <Book: 西游记>]>
红楼梦 ----> 1
西游记 ----> 0
---------------------------------------------
ret=Book.objects.all().annotate(c=Count('authors')).values('name','c')
print(ret)
------------------------------------
<QuerySet [{'name': '红楼梦', 'c': 1}, {'name': '西游记', 'c': 0}]># 统计每一个出版社的最便宜的书(以谁group by 就以谁为基表)
ret=Publish.objects.all().annotate(m=Min('book__price')).values('name','m')
print(ret)
------------------------------------------
<QuerySet [{'name': '北京出版社', 'm': Decimal('34.50')}]>
# 统计每一本以py开头的书籍的作者个数
ret=Book.objects.all().filter(name__startswith='py').annotate(c=Count('authors')).values('name','c')
print(ret)
--------------------------------
<QuerySet [{'name': 'py书大全', 'c': 0}]># 总结:  group by 谁,就以谁做基表,filter过滤,annotate取分组,values取值# 总结终极版本# values在前,表示group by 在后,表示取值# filter在前,表示where条件,在后表示having# 统计每一本以py开头的书籍的作者个数--套用模板
ret=Book.objects.all().values('name').filter(name__startswith='py').annotate(c=Count('authors')).values('name','c')
print(ret)
-----------------------------------
<QuerySet [{'name': 'py书大全', 'c': 0}]># 查询各个作者出的书的总价格
ret=Author.objects.all().values('name').annotate(s=Sum('book__price')).values('name','s')
print(ret)
--------------------------------------------------------
<QuerySet [{'name': 'egon', 's': Decimal('34.50')}]>ret=Author.objects.all().annotate(s=Sum('book__price')).values('name','s')
print(ret)
----------------------------------------------------------
<QuerySet [{'name': 'egon', 's': Decimal('34.50')}]># 查询名字叫egon作者书的总价格
ret=Author.objects.all().values('pk').filter(name='egon').annotate(s=Sum('book__price')).values('name','s')
print(ret)
-----------------------------------
<QuerySet [{'name': 'egon', 's': Decimal('34.50')}]># 查询所有作者写的书的总价格大于30
ret=Author.objects.all().values('pk').annotate(s=Sum('book__price')).filter(s__gt=2).values('name','s')
print(ret)
-----------------------------------------
<QuerySet [{'name': 'egon', 's': Decimal('34.50')}]>ret=Author.objects.all().annotate(s=Sum('book__price')).filter(s__gt=30).values('name','s')
print(ret)
-------------------------------------------
<QuerySet [{'name': 'egon', 's': Decimal('34.50')}]># 总结终极版本
# values在前,表示group by 在后,表示取值
# filter在前,表示where条件,在后表示having# 统计不止一个作者的图书
ret = Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
ret=Book.objects.all().values('pk').annotate(c=Count('authors')).filter(c__gt=1).values('name','c')
print(ret)

七、F函数

models.py

from django.db import models# Create your models here.#用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id
# ManyToManyField会自动创建第三张表
# *************重点
# 一对一的关系:OneToOneField
# 一对多的关系:ForeignKey
# 多对多的关系:ManyToManyFieldclass Publish(models.Model):# id如果不写,会自动生成,名字叫nid,并且自增id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)addr = models.CharField(max_length=64)email = models.EmailField()class Author(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)# 数字类型sex = models.IntegerField()# 可以用ForeignKey,但是得设置唯一性约束,会报警告,不建议用,建议用OneToOneField# authordetail=models.ForeignKey(unique=True)# to='AuthorDetail'  加引号,这个表能找到就可以,不用引号,类必须在上面定义authordetail = models.OneToOneField(to='AuthorDetail', to_field='id')def __str__(self):return self.nameclass AuthorDetail(models.Model):id = models.AutoField(primary_key=True)phone = models.CharField(max_length=32)addr = models.CharField(max_length=64)class Book(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32,db_index=True)price = models.DecimalField(max_digits=5, decimal_places=2)# 阅读数reat_num=models.IntegerField(default=0)# 评论数commit_num=models.IntegerField(default=0)publish = models.ForeignKey(to=Publish, to_field='id',on_delete=models.CASCADE)authors = models.ManyToManyField(to=Author)# test=models.PositiveSmallIntegerField()def __str__(self):return self.nameclass Test(models.Model):name=models.CharField(max_length=32)class Meta:db_table='aaa'

python3 manage makemigrations
python3 manage migrate

import osif __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day77.settings")import djangodjango.setup()from app01.models import *
from django.db.models import F
# 查询评论数大于阅读数的书
ret=Book.objects.all().filter(commit_num__gt=F('reat_num'))
print(ret)
---------------------------------
<QuerySet [<Book: 红楼梦>]># 把所有书的评论数加100
ret=Book.objects.all().update(commit_num=F("commit_num")+100)
print(ret)# 把红楼梦这本书的阅读数减5
ret = Book.objects.all().filter(name='红楼梦').update(reat_num=F('reat_num') - 5)
print(ret)# Q函数 为了表示与& ,或 | ,非 ~,
from django.db.models import Q
# 查询作者不是lqz的书
ret=Book.objects.filter(~Q(authors__name='lqz'))
print(ret)
<QuerySet [<Book: 红楼梦>, <Book: 西游记>, <Book: py书大全>]>
#     构建很复杂的逻辑,需要用括号来区分
ret = Book.objects.filter((Q(name='红楼梦') & Q(price__gt=100)) | Q(pk__gt=2))
print(ret)
------------------------------
<QuerySet [<Book: py书大全>]>

总结:

1基于双下划线的跨表查询套路一样,用__跨表-一对多-多对多2 聚合查询-聚合函数from django.db.models import Avg,Count,Max,Min,Sum# 计算所有图书的平均价格# ret=Book.objects.all().aggregate(Avg('price'))# print(ret)3分组查询终极总结:values在前,表示group by,在后,表示取值filter在前,表示过滤(where),在后,表示having(对分组之后的结果再进行过滤)4 F查询与Q查询-F为了字段=后面的值,不能放字段,所以用F函数包裹一下就可以了-Q为了构造与&,或|,非~的关系5 常用字段:必须记住,非常用字段,了解即可6 orm字段参数:-null  可以为空-unique  唯一性约束-default 默认值-db_index 为该字段建索引-只给日期类型和时间类型用-auto_now_add    新增数据时,默认把当前时间存入-auto_now        修改的时候,默认把当前时间存入7 关系字段ForeignKey-to  关联哪个表-to_field 关联的字段-related_name 反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'。(一般不要用)-related_query_name :基于双下划线的反向查询之前按表名小写(一般不要用)-on_delete:models.CASCADE,models.SET_NULL-db_constraint:db_constraint=False代表,不做外键关联作业:1 手动创建第三张表,并且新增,删除,查询数据2 整理博客3 上课讲的敲一遍

转载于:https://blog.51cto.com/silencezone/2361369

九、多表模型创建,一对一,一对多,基于对像的多表模型等相关推荐

  1. bim 模型web页面展示_基于HTML5/WebGL技术的BIM模型轻量化Web浏览解决方案

    互联网技术的兴起极大得改变了我们的娱乐.生活和生产方式.尤其是HTML5/WebGL技术的发展更是在各个行业内引起颠覆性的变化,大家感受最深刻的可能是游戏.电商.O2O等和我们生活息息相关的行业,但这 ...

  2. 数据表的创建(一对多,多对多)

    前言 项目开发过程中,数据库表会出现很多映射关系,不只有一对多,还有一对多,多对多.则数据库实体间有三种对应关系:一对一,一对多,多对多. 一.实例 一对一关系实例: 一个学生对应一个学号. 一对多关 ...

  3. Oracle系列之七:表的创建与管理

    Oracle表的创建与管理 1. 表的创建 2. 表的修改 3. 表中数据的增删改查 4. 表的Merge 5. 表的删除 6. 表的重命名 7. 表的索引 8. 表的约束 9. dual表 表是Or ...

  4. 数据库、表的创建与修改

    目录 一.实验目的 1.实验6.6 MySQL安装创建和维护数据库实验 2.实验7.8 数据表的创建与修改管理实验 二.实验内容 1.验证性实验 三.设计性实验 四.实验小结: 一.实验目的 1.实验 ...

  5. 3dsmax 模型创建+原生贴图+obj/mtl+three.js 实现WEB3D

    3dsmax模型创建+原生贴图 模型创建请参考另一篇我的文章 3dsmax 模型创建+原生贴图(多图) 为何要原生贴图? 因为three.js只支持原生贴图的obj/mtl文件 obj/mtl导出 T ...

  6. BIM研究-基于HTML5/WebGL技术的BIM模型轻量化Web浏览解决方案

    内容来源:http://developer.51cto.com/art/201601/504553.htm 根据运维系统的特点,运维人员可能并不熟悉建筑建模软件的使用,同时让运维人员使用建模软件来做运 ...

  7. mysql-表关系模型,一对一,一对多,多对多

    一对一关系模型 >生活实例: 民政局登记的数据表,是一对一的关系 一公民,只能够有一位合法的配偶 >操作 民政局会有一个表 字段会有 主键id,男方身份证号,女方身份证号 然后会往表中插入 ...

  8. mysql 树形结构_结合RBAC模型讲解权限管理系统需求及表结构创建

    结合RBAC模型讲解权限管理系统需求及表结构创建 在本号之前的文章中,已经为大家介绍了很多关于Spring Security的使用方法,也介绍了RBAC的基于角色权限控制模型.但是很多朋友虽然已经理解 ...

  9. 7. MyBatis多表查询 - 一对一 - 一对多 - 多对多

    7. MyBatis多表查询 - 一对一 - 一对多 - 多对多 前言 在前面的篇章,我们已经熟悉了单表查询,下面我们来看看如何进行 多表查询. 数据准备 create database if not ...

最新文章

  1. 关于python中的dict和defaultdict
  2. 人类正在进入超级智能时代,论一种新超级智能的崛起
  3. 码上公益首秀,让科技更有温度!
  4. 有三AI不得不看的几十篇技术综述
  5. SQL语句中,创建标识列、默认值及各种约束的语法介绍
  6. 配置V530交换机步骤
  7. 14岁女孩模仿视频中易拉罐做爆米花意外身亡 博主办公室小野回应...
  8. 这款老不死的笔记本,产品小姐姐的最爱......
  9. 蛮力法 —— 求解最大连续子序列和问题
  10. 普通用户登录PLSQL后提示空白OK对话框错误
  11. 前端高效开发必备的 js 库大全
  12. windows11 安全中心点击进去内容空白解决方法
  13. 在哪里能看到计算机缓存大小,怎么查看电脑硬盘缓存大小
  14. JavaScript实现人民币大小写转换
  15. Android 调用谷歌原生语音识别
  16. git常用命令梳理及常见开发场景总结
  17. linux 内存使用计算
  18. FleaPHP 开发指南 - 7. 数据表关联
  19. alibaba的druid连接池的监控的两种方法
  20. MS17-010永恒之蓝漏洞利用,win32安装,windows 7 32位

热门文章

  1. 小熊维尼项目冲刺 第三天
  2. 版本控制工具——Git常用操作(下)
  3. Qt OpenGL裁剪测试
  4. 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue
  5. buildroot的使用简介【转】
  6. Eclipse自动代码补全
  7. blank space in latex math environment
  8. 对list字段属性的部分修改的application
  9. 简单的聊聊,顺便招前端
  10. 【转】如何修改Chrome缓存目录的地址