文章目录
一 创建模型(一) 模型创建(二) 外键关系建立问题
二 添加表记录(一) 一对多添加记录(二) 多对多添加记录(三) 多对多关系常用的API
三 基于对象的跨表查询(一) 两种跨表查询方式及正、反向查询(二) 一对多查询(三) 一对一查询(四) 多对多查询
四 基于双下划线的跨表查询(一) 一对多查询(二) 多对多查询(三) 一对一查询(四) 进阶之连续跨表查询(五) 总结
五 聚合查询与分组查询(一) 聚合查询(二) 分组查询(三) 多表查询练习
六 F查询与Q查询(一) F查询(二) Q查询
七 其他补充(一) 安装模块相关补充(二) 前后端分离和混合开发
一 创建模型
(一) 模型创建
1) 图书表:book
,作者表:author,作者详情表:authordetail,出版社表:publish
,(第三张中间表
)。
2) 作者跟作者详情:是一对一,关联字段写在哪一方都可以
3) 图书跟出版社:是一对多,【一对多关系一旦确立,关联字段写在多的一方】
4) 图书和作者:是多对多,多对多的关系需要建立第三张表(可以自动生成)
5) models
.py中把关系建立出来
from django
.db
import models
class Publish(models
.Model
):
id = models
.AutoField
(primary_key
=True)
name
= models
.CharField
(max_length
=32)
addr
= models
.CharField
(max_length
=128)
phone
= models
.CharField
(max_length
=64)
email
= models
.EmailField
()
class Meta:
verbose_name
= '出版社'
verbose_name_plural
= '出版社'
def __str__(self
):
return self
.name
"""以下为Book表后添加的字段,添加后做一下数据库迁移"""
class 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_date
= models
.DateTimeField
(auto_now_add
=True)
publish
= models
.ForeignKey
(to
='Publish', on_delete
=models
.SET_NULL
, null
=True)
authors
= models
.ManyToManyField
(to
='Author')
class Author(models
.Model
):
id = models
.AutoField
(primary_key
=True)
name
= models
.CharField
(max_length
=32)
age
= models
.SmallIntegerField
()
author_detail
= models
.OneToOneField
(to
='AuthorDetail', to_field
='id', on_delete
=models
.CASCADE
)
class AuthorDetail(models
.Model
):
id = models
.AutoField
(primary_key
=True)
gender
= models
.SmallIntegerField
()
addr
= models
.CharField
(max_length
=64)
phone
= models
.BigIntegerField
()
6) 同步到mysql数据库
-配置文件
-pymysql
.install_as_mysqldb
()
-公司可能用的mysqlclient
-两条命令
7) 2.x版本的django
-外键字段必须加 参数:on_delete
-1.x版本不需要,默认就是级联删除
-举例假设:
删除出版社,该出版社出版的所有图书也都删除,on_delete
=models
.CASCADE
删除出版社,该出版社出版的图书不删除,设置为空on_delete
=models
.SET_NULL
,null
=True
删除出版社,该出版社出版的图书不删除,设置为默认on_delete
=models
.SET_DEFAULT
,default
=0
1) 便于理解:一对一的本质是 ForeignKey
+unique
(二) 外键关系建立问题
1) 关联字段与外键约束没有必然的联系(建关联字段是为了进行查询,建约束是为了不出现脏数据)
2) 默认情况,关联关系建好以后,外键约束就自然建立了
3) 实际工作中,外键约束一般不建(影响效率),都是人为约束(代码约束)
-db_constraint
=False
4) 表模型和数据库表的对应,不要直接修改表(这是可以的,但是不建议),要修改表模型,同步到表中
二 添加表记录
(一) 一对多添加记录
import os
if __name__
== '__main__':
os
.environ
.setdefault
('DJANGO_SETTINGS_MODULE', '项目名.settings')
import django
django
.setup
()
from app01
import models
publish_obj1
= models
.Publish
.objects
.create
(name
='北京出版社',addr
='北京',phone
='010-66666666',email
='bj@qq.com')
publish_obj2
= models
.Publish
.objects
.create
(name
='沙河出版社',addr
='北京',phone
='010-88888888',email
='sh@qq.com')
publish_obj3
= models
.Publish
.objects
.create
(name
='三体出版社',addr
='三体星',phone
='010-77777777',email
='st@qq.com')
book_obj1
= models
.Book
.objects
.create
(name
='西游记', price
='21', publish_id
=1)
book_obj2
= models
.Book
(name
='红楼梦', price
='22.22', publish_id
=1)
book_obj2
.save
()
book_obj3
= models
.Book
.objects
.create
(name
='诛仙', price
='66.66', publish_id
=1)
book_obj4
= models
.Book
.objects
.create
(name
='Python从入门到入狱', price
='0.5', publish_id
=2)
book_obj5
= models
.Book
.objects
.create
(name
='三体', price
='99.99', publish_id
=3)
book
= models
.Book
.objects
.get
(name
='红楼梦')
1 email可以不传email,本质就是varchar(admin中会判断)
2 新增图书:
-publish
=publish
-publish_id
=publish
.id
3 写在表模型中的publish字段,到数据库中会变成publish_id
(ForeignKey
)
4 查到book对象以后
-book
.publish 对象
-book
.publish_id
id号,数字
(二) 多对多添加记录
author_detail_obj1
= models
.AuthorDetail
.objects
.create
(gender
=0, addr
='北京沙河', phone
=15512345678)
author_detail_obj2
= models
.AuthorDetail
.objects
.create
(gender
=0, addr
='北京沙河', phone
=15587654321)
author_detail_obj3
= models
.AuthorDetail
.objects
.create
(gender
=0, addr
='福建福州', phone
=17767676767)
author_detail_obj4
= models
.AuthorDetail
(gender
=0, addr
='山西娘子关', phone
=18878787878)
author_detail_obj4
.save
()
author_list
= {'刘老牛': [18, 1], '小矮根': [81, 2], '萧鼎': [33, 3], '刘慈欣': [32, 4]}
for a_name
, age_id
in author_list
.items
():
models
.Author
.objects
.create
(name
='%s' % a_name
, age
=age_id
[0], author_detail_id
=age_id
[1])
book_obj1
= models
.Book
.objects
.get
(name
='西游记')
book_obj2
= models
.Book
.objects
.get
(name
='红楼梦')
book_obj3
= models
.Book
.objects
.get
(name
='诛仙')
book_obj4
= models
.Book
.objects
.get
(name
='Python从入门到入狱')
book_obj5
= models
.Book
.objects
.get
(name
='三体')
book_obj1
.authors
.add
(1)
book_obj2
.authors
.add
(2)
book_obj3
.authors
.add
(3)
book_obj4
.authors
.add
(1, 2)
book_obj5
.authors
.add
(4)
(三) 多对多关系常用的API
book_obj4
.authors
.set((3, 4))
book_obj4
.authors
.remove
(4)
book_obj4
.authors
.clear
()
book_obj4
.authors
.add
(1, 2)
三 基于对象的跨表查询
(一) 两种跨表查询方式及正、反向查询
-基于对象的跨表查询:子查询
-基于双下划线的跨表查询:关联查询,连表查询
(二) 一对多查询
book_obj
= models
.Book
.objects
.get
(id=1)
publish
= book_obj
.publish
print(publish
.addr
)
addr
= models
.Book
.objects
.get
(id=1).publish
.addr
print(addr
)
publish
= models
.Publish
.objects
.get
(name
='北京出版社')
books
= publish
.book_set
.all()
print(books
)
(三) 一对一查询
author_detail
= models
.AuthorDetail
.objects
.filter(addr__contains
='北京')
for k
in author_detail
:
print(k
.author
.name
)
author
= models
.Author
.objects
.get
(name
='小矮根')
print(author
.author_detail
.addr
)
(四) 多对多查询
book
= models
.Book
.objects
.get
(name
='Python从入门到入狱')
authors
= book
.authors
.all()
for author
in authors
:
print(author
.name
)
print(author
.author_detail
.phone
)
author_smallegon
= models
.Author
.objects
.get
(name
='小矮根')
books
= author_smallegon
.book_set
.all()
for book
in books
:
print(book
.name
)
author_detail
= models
.AuthorDetail
.objects
.get
(addr
='山西娘子关')
author
= author_detail
.author
books
= author
.book_set
.all()
print(books
[0].name
)
author_detail
= models
.AuthorDetail
.objects
.get
(addr
='山西娘子关')
author
= author_detail
.author
books
= author
.book_set
.all()
for book
in books
:
print(book
.publish
.name
)
四 基于双下划线的跨表查询
(一) 一对多查询
res
= models
.Publish
.objects
.filter(name
='北京出版社').values
('book__name', 'book__price')
print(res
)
res
= models
.Book
.objects
.filter(publish__name
='北京出版社').values
('name', 'price')
print(res
)
(二) 多对多查询
res
= models
.Book
.objects
.filter(authors__name
='刘老牛').values
('name', 'price')
print(res
)
res
= models
.Author
.objects
.filter(name
='刘老牛').values
('book__name', 'book__price')
print(res
)
(三) 一对一查询
res
= models
.Author
.objects
.filter(name
='萧鼎').values
('author_detail__phone')
print(res
)
res
= models
.AuthorDetail
.objects
.filter(author__name
='萧鼎').values
('phone')
print(res
)
(四) 进阶之连续跨表查询
res
= models
.Publish
.objects
.filter(name
='北京出版社').values
('book__name', 'book__authors__name')
print(res
)
res
= models
.Author
.objects
.filter(book__publish__name
='北京出版社').values
('book__name', 'name')
print(res
)
res
= models
.Book
.objects
.filter(publish__name
='北京出版社').values
('name', 'authors__name')
print(res
)
res
= models
.AuthorDetail
.objects
.filter(phone__startswith
='155').values
('author__book__name', 'author__book__publish__name')
print(res
)
res
= models
.Author
.objects
.filter(author_detail__phone__startswith
='155').values
('book__name', 'book__publish__name')
print(res
)
(五) 总结
-filter,values,vlues_list中写 __ 连表
- 正向:字段名
- 反向:表名小写
五 聚合查询与分组查询
(一) 聚合查询
aggregate
()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的【字典】。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
from django
.db
.models
import Avg
, Max
, Min
, Count
, Sum
book
= models
.Book
.objects
.all().aggregate
(Avg
('price'))
print(book
)
book
= models
.Book
.objects
.all().aggregate
(count
=Count
('id'))
print(book
)
book
= models
.Book
.objects
.all().aggregate
(min=Min
('price'))
print(book
)
book
= models
.Book
.objects
.all().aggregate
(max=Max
('price'))
print(book
)
(二) 分组查询
'''
id name price publish_id
1 西游记 21.00 1
2 红楼梦 22.22 1
3 诛仙 66.66 1
4 Python从入门到入狱 0.50 2
5 三体 99.99 3
'''
from django
.db
.models
import Avg
, Max
, Min
, Count
, Sum
ret
= models
.Book
.objects
.values
('publish_id').annotate
(avg
=Avg
('price')).values
('publish_id', 'avg')
print(ret
)
ret
= models
.Book
.objects
.filter(publish_id__gt
=1).values
('publish_id').annotate
(avg
=Avg
('price')).values
('publish_id', 'avg')
print(ret
)
ret
= models
.Book
.objects
.filter(publish_id__gt
=1).values
('publish_id').annotate
(avg
=Avg
('price')).filter(avg__gt
=30).values
('publish_id', 'avg')
print(ret
)
(三) 多表查询练习
ret
= models
.Book
.objects
.get
(pk
=1)
print(ret
)
ret
= models
.Publish
.objects
.values
('pk').annotate
(count
=Count
('book__id')).values
('name', 'count')
print(ret
)
ret
= models
.Book
.objects
.values
('publish_id').annotate
(count
=Count
('publish_id')).values
('publish__name', 'count')
print(ret
)
ret
= models
.Author
.objects
.values
('pk').annotate
(max=Max
('book__price')).values
('name', 'max')
print(ret
)
ret
= models
.Author
.objects
.annotate
(max=Max
('book__price')).values
('name', 'max')
print(ret
)
ret
= models
.Book
.objects
.values
('authors__id').annotate
(max=Max
('price')).values
('authors__name', 'max')
print(ret
)
ret
= models
.Book
.objects
.values
('pk').annotate
(count
=Count
('authors__id')).values
('name', 'count')
print(ret
)
ret
= models
.Author
.objects
.values
('book__id').annotate
(count
=Count
('id')).values
('book__name', 'count')
print(ret
)
ret
= models
.Book
.objects
.values
('pk').annotate
(count
=Count
('authors__id')).filter(count__gt
=1).values
('name', 'count')
print(ret
)
ret
= models
.Author
.objects
.values
('book__id').annotate
(count
=Count
('id')).filter(count__gt
=1).values
('book__name', 'count')
print(ret
)
ret
= models
.Book
.objects
.filter(price__gt
=10).values
('pk').annotate
(count
=Count
('authors__id')).values
('name', 'count')
print(ret
)
ret
= models
.Book
.objects
.filter(price__gt
=10).values
('pk').annotate
(count
=Count
('authors__id')).filter(count__gt
=1).values
('name', 'count')
print(ret
)
六 F查询与Q查询
(一) F查询
from django
.db
.models
import F
ret
= models
.Book
.objects
.all().update
(read_num
=F
('read_num')+1)
print(ret
)
ret
= models
.Book
.objects
.all().filter(commit_num__gt
=F
('read_num'))
for i
in ret
:
print(i
.name
, end
='<-->')
ret
= models
.Book
.objects
.all().filter(commit_num__gt
=F
('read_num')*2)
print(ret
)
(二) Q查询
from django
.db
.models
import Q
ret
= models
.Book
.objects
.filter(Q
(name
='红楼梦') | Q
(price__gt
=90))
print(ret
)
ret
= models
.Book
.objects
.filter(Q
(name
='红楼梦') & Q
(price__gt
=90))
print(ret
)
ret
= models
.Book
.objects
.filter(~Q
(name
='红楼梦'))
print(ret
)
ret
= models
.Book
.objects
.filter((Q
(name
='红楼梦') & Q
(price__gt
=90)) | Q
(id__gt
=3))
print(ret
)
七 其他补充
(一) 安装模块相关补充
pip3 install django
pip3 install django
.whl
到达安装目录,setup
.py所在的目录
python setup
.py build
python setup
.py install
豆瓣源会把pypi,包拉到自己的服务器上,以后你再下,去它的服务器上下,所以速度快
(二) 前后端分离和混合开发
1) 模板语言:每个语言的web框架都会有模板语言,django
---》dtl
2) 模板语言的渲染,是在后端完成的
3) 用php写前端(html,css
,js)
(是错误说法
)
4) 前后端分离:前后端交互,统一全用json格式
5) 前端只专注于写前端
(vue
,react
:前端工程化
),后端只专注于写后端(提供接口,交互json格式数据)