初识Django
Django ORM表的创建和增删改查
django请求生命周期流程图和路由层
Django视图层,模版层
ORM单表关键字查询
#增
#直接录入相关的主键字段数据
models.Book.objects.create(title='三国演义',price=123.32,publish_id=1)
# 有主键就传主键,没主键就传数据对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='人性的弱点',price=55.78,publish=publish_obj
#改
models.Book.objects.filter(pk=2).update(publish_id=2)
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=3).update(publish=publish_obj)
外键字段多对多字段操作
#增
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.add(1) # 书籍对象点多对多虚拟字段就相当于在操作第三张关系表
book_obj.authors.add(1,2)
#增
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = models.Author.objects.filter(pk=3).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj,author_obj1)
"""
add
在第三张关系表中添加数据
括号内既可以传主键字段也可以传数据对象 并且都支持传多个
"""
#改
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.set([1,])
book_obj.authors.set([1,2])
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.authors.set([author_obj])
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set([author_obj])
book_obj.authors.set([author_obj,author_obj1])
"""
set
在第三张关系表中修改数据
括号内需要传一个可迭代对象
可迭代对象里面的元素既可以传主键字段也可以传数据对象 并且都支持传多个
"""
# 删
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.remove(1)
book_obj.authors.remove(1,2)
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj, author_obj1)
"""
remove
在第三张关系表中删除数据
括号内既可以传主键字段也可以传数据对象 并且都支持传多个
"""
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear() # 清空当前书籍与作者的所有绑定关系
"""
clear
在第三张关系表中清空数据
括号内无需传值
"""
1、查询主键为的书籍
book_obj=models.Book.objects.filter(pk=2).first()
res = book_obj.publish
print(res, res.pk, res.name, res.addr)
2.查询主键为3的书籍对应的作者
book_obj = models.Book.objects.filter(pk=3).first()
res = book_obj.authors
print(res)
#输出结果
app01.Author.None
res = book_obj.authors.all()
print(res)
for author_obj in res:
print(author_obj.pk)
print(author_obj.name)
print(author_obj.age)
# 可以拿到所有的对象
3、查询卡耐基的详细数据
# 先查询作者对象
author_obj = models.Author.objects.filter(name='卡耐基').first()
res = author_obj.author_detail
print(res,res.phone)
总结:基于对象的正向查询,数据对象点了外键字段之后,是否需要在点all 取决于关联的数据有几项,单个无须点,多个则需要点
4、查询北京科技出版社出版的书籍
# 先查询北京科技出版社对象
publish_obj = models.Publish.objects.filter(name='北京科技出版社').first()
# 基于北京科技出版社对象查询书籍对象(北京科技出版社对象跟书籍的外键字段在书籍表中,所以为反向)
查询zz写过的书
# 先查询zz对象
author_obj = models.Author.objects.filter(name='卡耐基').first()
# 在基于对象查询书籍对象,对象跟书籍的外键字段在书籍表中 所以为反向
res = author_obj.book_set.all()
print(res)
查询电话是432的作者姓名
查询432详情对象
author_obj = models.AuthorDetail.objects.filter(phone=432).first()
res = author_detail_obj.author
print(res)
1、查询主键为2的数据对应的出版社
res = models.Book.objects.filter(pk=2).values('publish__name','publish__addr')
2、查询主键为3的书籍对应的作者
res = models.Book.objects.filter(pk=2).values_list('author__name','author__age')
print(res)
3、查询zz的详细数据
res = models.Author.objects.filter(name='zz').values('authors_detail__phone','authors_detail__addr')
4、查询书籍pk为2的作者电话
res = models.Book.objects.filter(pk=2).values('author__')
5、查询北方出版社出版的书籍
res = models.Publish.objects.filter(name='四川科技出版社').values('book__title','book__price')
print(res)
查询电话是432的作者姓名
res = models.AuthorDetail.objects.filter(phone=432).values('author__name')
print(res)
查询主键为2的书籍对应的出版社(不能点书籍)
res = models.Publish.objects.filter(book__pk=2)
2.查询主键为3的书籍对应的作者
res = models.Author.objects.filter(book__pk=2)
print(res) # , ]>
3、查询高得的详细数据
res = models.AuthorDetail.objects.filter(author__name='高得')
print(res) # ]>
4、查询上海联合出版社出版的书籍
res = models.Book.objects.filter(publish__name='上海联合出版社')
print(res)
5、查询zz写过的书
res = models.Book.objects.filter(authors__name='zz')
print(res)
# ]>
6.查询电话是982的作者姓名
res = models.Author.objects.filter(author_detail__phone=982)
print(res)
from django.db.models import Max, Min, Sum, Count, Avg
统计书的总价格
res = models.Book.objects.aggregate(Sum('price'))
print(res)
统计书的总数
res = models.Book.objects.aggregate(Count('pk'))
print(res)
#{'pk__count': 6}
1、统计每一本书的作者个数
vim /usr/local/etc/my.cnf
[mysqld]
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
res =
models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price','name','book__title')
print(res)
2、统计每个出版社卖出最便宜的书
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price','name','book__title')
print(res)
3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1)
print(res)
4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(price_sum=Sum('book__price')).values('name','price_sum')
print(res)
"""
1.大的分组
models.表名.objects.annotate 按照models后面的表名分组(主键)
2.小的分组
models.表名.objects.values('price').annotate() 按照values括号内指定的字段分组
"""
功能:获取数据库中字段原有的数据
模块导入
from django.db.models import F
1、将所有的数据价格提升100块
models.Book.objects.update(price=F('price')+100)
2、将所有书后加上爆款
from django.db.models.functions import Concat
from django.db.models import Values
res = models.Book.objects.update(title=Cancat(F('title'),Value('爆款')))
"""
F查询默认操作数字类型 如过需要操作字符串类型需要以上操作
"""
3、查询库存数大于卖出数的书籍
res = models.Book.objects.filter(kucun__gt=F('maichu'))
print(res)
#]>
filter括号内多个条件均为and关系
查询主键为3或着卖出数为1000的书籍
#基本用法
from django.db.models import Q
res = models.Book.objects.filter(Q(pk=3), Q(maichu=1000)) # 逗号分隔为and关系
res = models.Book.objects.filter(Q(pk=3) | Q(maichu=1000)) # |分隔为or关系
res = models.Book.objects.filter(~Q(pk=3) | Q(maichu=1000)) # ~分隔为not关系
print(res)
#进阶用法
q = Q() # 默认多个条件之间也是and关系
q.connector = 'or' # 也可以修改链接关系
q.children.append(('title', '三国演义爆款'))
q.children.append(('title__contains', '爆'))
q.children.append(('price', 1123))
res = models.Book.objects.filter(q)
print(res)
from django.db import transaction
事务
买一本 跟jason学Linux 书
在数据库层面要做的事儿
1. 创建一条订单数据
2. 去产品表 将卖出数+1, 库存数-1
from django.db.models import F
开启事务处理
try:
with transaction.atomic():
创建一条订单数据
models.Book.objects.create(num="110110111", product_id=1, count=1)
能执行成功
models.Book.objects.filter(id=1).update(kucun=F("kucun") - 1, maichu=F("maichu") + 1)
except Exception as e:
print(e)
transaction.rollback() # 回滚
transaction.commit() # 提交
from django.db import transaction
# 方式1:装饰器
@transaction.atomic
# 方式2:with上下文
with transaction.atomic():
transaction.rollback()
transaction.commit()
res = models.Book.objects.all()
res1 = models.Book.objects.filter(pk=1)
only:获取指定字段对应数据,并且封装成字典
res = models.Book.objects.values('title')
for d in res:
print(d,type(d))
print(d.get('title'))
defer:获取指定字段对应数据,并封装成对象
res = models.Book.objects.only('title')
for obj in res:
print(obj.title)
print(obj.price)
print(obj.publish_time)
总结
- 对象点击only括号内填写字段名称不会走数据库查询,但括号内不存在的字段名称则每次都会走数据库
res = models.Book.objects.defer('title')
for obj in res:
print(obj.price)
"""
与only互为反操作
"""
res = models.Book.objects.filter(pk=3).first()
print(res.publish.name)
only方法会返回一个对象的数据集 对象默认只含有括号内指定字段的数据,如果对象点击括号内没有指定的字段也可以获取到数据只不过每次都需要重新走数据库查询
defer与only刚好相反
res = models.Book.objects.select_related('publish')
for obj in res:
print(obj.publish.name)
"""
内部是连表操作 会将外键关联的表与当前表拼接 之后将所有的数据全部封装到数据对象中
之后对象无论查询哪个表的数据都不再走数据库查询
select_related括号内只能放外键字段 并且不支持多对多外键字段
"""
res = models.Book.objects.prefetch_related('publish')
for obj in res:
print(obj.publish.name)
"""
内部是子查询操作 先查询所有的书籍数据 之后查询每本书籍数据对应的出版社数据
之后将总数据封装到数据对象中
"""
两者括号内都只能放外键字段(一对一和一对多)
select_related内部相当于连表操作 将所有的表拼接到一起之后,再将表中所有的数据全部封装到数据对象中
prefetch_related内部相当于子查询 先查一张表之后将关联的表数据也 查询出来 再封装到数据对象中
AutoField() #专门用于主键
'需要指定primary key'
CharField() #长整型
'需要指定max_lengh参数 varchar()'
IntegerField() #整数
DecimalField() #小数
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
DateField()
DateTimeField()
"""
auto_now 每次更新数据记录的时候会更新该字段
auto_now_add 创建数据记录的时候会把当前时间添加到数据库
"""
BooleanField() # 布尔值类型
"""
传布尔值 存0或1
is_delete = models.BooleanField()
is_alive = models.BooleanField()
is_buy = models.BooleanField()
"""
TextField() # 文本类型
"""
专门用于存储大段文本数据
比如文章内容...
"""
EmailField() # 邮箱类型
FileField()
- 字符串,路径保存在数据库,文件上传到指定目录
- upload_to = "" 上传文件的保存路径
"""自定义字段:为了防止django版本与最新的数据库产生差异"""
class MyCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super().__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection):
return 'char(%s)' % self.max_length
# 重要参数
null = True
default = None
unique 如果设置为unique=True 则该字段在此表中必须是唯一的 。
db_index 如果db_index=True 则代表着为此字段设置索引。
# 外键字段
to、to_field、on_delete、related_name(给外键字段起别名 用于正反向)
db_constraint
"""自行总结django1.X与django2.X|3.X外键字段使用的区别"""
Django1.0:hbook = models.ForeignKey('BookInfo') # 1中默认是级联的
Django2.0:hbook = models.ForeignKey('BookInfo', on_delete=models.CASCADE) # 2中需要手动设置级联