罗湖实惠的网站建设费用,广告设计公司哪家好,手提包 东莞网站建设,官方旗舰店【一】前言 Django自带的sqlite3数据对日期格式不敏感#xff0c;处理的时候容易出错 【二】单表操作
【1】数据的增加
from django.test import TestCase# Create your tests here.
import osif __name__ __main__:os.environ.setdefault(DJANGO_SETTIN…【一】前言 Django自带的sqlite3数据对日期格式不敏感处理的时候容易出错 【二】单表操作
【1】数据的增加
from django.test import TestCase# Create your tests here.
import osif __name__ __main__:os.environ.setdefault(DJANGO_SETTINGS_MODULE, day07.settings)import djangodjango.setup()# 在下面书写我们需要测试的代码# 即所有的测试代码都必须等待环境准备完毕之后才能书写from app01 import models# (1)增加数据# register_time (1)支持自己指定传值resmodels.User.objects.create(namejason,age18,register_time2002-1-21)# 返回值为对象本身print(res) # User object# register_time (2)支持传入日期对象import datetime# 生成一个当前的时间对象c_time datetime.datetime.now()user_obj models.User(nameegon,age84,register_timectime)# 保存数据user_obj.save()
【2】数据的删除
# 【2】删除数据
# pk : 自动查找到当前表的主键字段指代的就是当前表的主键字段
# 使用 pk 后不需要知道当前表的主键字段 他会自动帮我们查找并匹配
# (1)方式一
res models.User.objects.filter(pk2).delete()
print(res) # (1, {app01.User: 1})
# (2)方式二
# 拿到当前用户对象
user_obj models.User.objects.filter(pk1).first()
# 利用对象的方法进行删除
user_obj.delete()
【3】数据的更改
# 【3】数据的更改
# (1)方式一
res models.User.objects.filter(pk4).update(nameegonDSB)
print(res) # 1
# (2)方式二
# 返回的就是当前的数据对象
# 不推荐使用 如果查询的数据不存在会直接报错 fileter不会
user_onj models.User.objects.get(pk4)
# user_obj models.User.objects.filter(pk6)get方法返回的直接就是当前数据对象但是该方法不推荐使用一旦数据不存在该方法会直接报错而filter则不会所以我们还是用filter
# 调用对象更改数据
user_onj.name egonPPP
user_onj.save()
【三】常见的十几种查询方法
# 必知必会13条1.all() 查询所有数据2.filter() 带有过滤条件的查询3.get() 直接拿数据对象 但是条件不存在直接报错4.first() 拿queryset里面第一个元素res models.User.objects.all().first()print(res)5.last()res models.User.objects.all().last()print(res)6.values() 可以指定获取的数据字段 select name,age from ... 列表套字典res models.User.objects.values(name,age) # QuerySet [{name: jason, age: 18}, {name: egonPPP, age: 84}]print(res)7.values_list() 列表套元祖res models.User.objects.values_list(name,age) # QuerySet [(jason, 18), (egonPPP, 84)]print(res)查看内部封装的sql语句上述查看sql语句的方式 只能用于queryset对象只有queryset对象才能够点击query查看内部的sql语句8.distinct() 去重res models.User.objects.values(name,age).distinct()print(res)去重一定要是一模一样的数据如果带有主键那么肯定不一样 你在往后的查询中一定不要忽略主键9.order_by()res models.User.objects.order_by(age) # 默认升序res models.User.objects.order_by(-age) # 降序print(res)10.reverse() 反转的前提是 数据已经排过序了 order_by()res models.User.objects.all()res1 models.User.objects.order_by(age).reverse()print(res,res1)11.count() 统计当前数据的个数res models.User.objects.count()print(res)12.exclude() 排除在外res models.User.objects.exclude(namejason)print(res)13.exists() 基本用不到因为数据本身就自带布尔值 返回的是布尔值res models.User.objects.filter(pk10).exists()print(res)
【四】测试脚本 测试脚本 当我们只想要测试Django中的某一个py文件的内容时我们可以不需要书写前后端交互的形式而是直接写一个测试脚本即可 测试环境的准备 在测试文件中书写下面内容 这内容其实就是最外部 manage.py 文件中的上面几句话 脚本代码无论是写在应用下的 tests.py文件还是自己新建文件将内容写在新文件中都会生效
from django.test import TestCaseimport os
import sysif __name__ __main__:os.environ.setdefault(DJANGO_SETTINGS_MODULE, day64.settings)import djangodjango.setup()# 在下面书写我们需要测试的代码# 即所有的测试代码都必须等待环境准备完毕之后才能书写 【五】查看内部SQL语句的方式
【1】方式一 只有queryset对象才能使用该方法 res models.User.objects.values_list(name,age) # QuerySet [(jason, 18), (egonPPP, 84)]
print(res.query)
【2】方式二 所有 SQL语句 都可以使用 在项目的settings.py文件中增加默认配置
LOGGING {version: 1,disable_existing_loggers: False,handlers: {console:{level:DEBUG,class:logging.StreamHandler,},},loggers: {django.db.backends: {handlers: [console],propagate: True,level:DEBUG,},}
}
【六】基于双下划线的查询
# 双下划线查询# 1 .年龄大于35岁的数据res models.User.objects.filter(age__gt35)print(res)# 2.年龄小于35岁的数据res models.User.objects.filter(age__lt35)print(res)# 3.大于等于32 小于等于32res models.User.objects.filter(age__gte32)print(res)res models.User.objects.filter(age__lte32)print(res)# 4.年龄是18 或者 32 或者40res models.User.objects.filter(age__in[18,32,40])print(res)# 5.年龄在18到40岁之间的 首尾都要res models.User.objects.filter(age__range[18,40])print(res)# 6.查询出名字里面含有s的数据 模糊查询res models.User.objects.filter(name__containss)print(res)#7. 是否区分大小写 查询出名字里面含有p的数据 区分大小写res models.User.objects.filter(name__containsp)print(res)#8. 忽略大小写res models.User.objects.filter(name__icontainsp)print(res)# 8.以什么开头/结尾res models.User.objects.filter(name__startswithj)res1 models.User.objects.filter(name__endswithj)print(res,res1)# 9.查询出注册时间是 2020 1月数据/年/月/日res models.User.objects.filter(register_time__month1)res models.User.objects.filter(register_time__year2020)res models.User.objects.filter(register_time__day28)
【七】多表查询引入
【1】数据准备
class Book(models.Model):title models.CharField(max_length32)price models.DecimalField(max_digits8,decimal_places2)publish_date models.DateField(auto_now_addTrue)# 一对多publish models.ForeignKey(toPublish)# 多对多authors models.ManyToManyField(toAuthor)class Publish(models.Model):name models.CharField(max_length32)addr models.CharField(max_length64)# varchar(254) 该字段类型不是给models看的 而是给后面我们会学到的校验性组件看的def __str__(self):return self.nameclass Author(models.Model):name models.CharField(max_length32)age models.IntegerField()# 一对一author_detail models.OneToOneField(toAuthorDetail)class AuthorDetail(models.Model):phone models.BigIntegerField() # 电话号码用BigIntegerField或者直接用CharFieldaddr models.CharField(max_length64)
【2】外键的增删改查
(1)一对多外键的增删改查
1.1 外键的增加 # 1 直接写实际字段 idmodels.Book.objects.create(title论语,price899.23,publish_id1)models.Book.objects.create(title聊斋,price444.23,publish_id2)models.Book.objects.create(title老子,price333.66,publish_id1)# 2 虚拟字段 对象publish_obj models.Publish.objects.filter(pk2).first()models.Book.objects.create(title红楼梦,price666.23,publishpublish_obj)
1.2 外键的删除
# (2)一对多的外键的删除
models.Publish.objects.filter(pk1).delete()
1.3 外键的修改
# (2)一对多的外键的修改
# - 直接写实际字段
models.Book.objects.filter(pk1).update(publish_id2)
# - 虚拟字段
publish_obj models.Publish.objects.filter(pk1).first()models.Book.objects.filter(pk1).update(publishpublish_obj)
(2)多对多外键的增删改查 多对多 增删改查 就是在操作第三张表 2.1 增加 book_obj models.Book.objects.filter(pk1).first()print(book_obj.authors) # 就类似于你已经到了第三张关系表了book_obj.authors.add(1) # 书籍id为1的书籍绑定一个主键为1 的作者book_obj.authors.add(2,3)# 可以传多个参数author_obj models.Author.objects.filter(pk1).first()author_obj1 models.Author.objects.filter(pk2).first()author_obj2 models.Author.objects.filter(pk3).first()book_obj.authors.add(author_obj)book_obj.authors.add(author_obj1,author_obj2)add给第三张关系表添加数据括号内既可以传数字也可以传对象 并且都支持多个
2.2 删除 remove 括号内既可以传数字也可以传对象 并且都支持多个 # 删book_obj.authors.remove(2)book_obj.authors.remove(1,3)author_obj models.Author.objects.filter(pk2).first()author_obj1 models.Author.objects.filter(pk3).first()book_obj.authors.remove(author_obj,author_obj1)
2.3 更改 set 括号内必须传一个可迭代对象该对象内既可以数字也可以对象 并且都支持多个 # 修改book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象book_obj.authors.set([3]) # 括号内必须给一个可迭代对象author_obj models.Author.objects.filter(pk2).first()author_obj1 models.Author.objects.filter(pk3).first()book_obj.authors.set([author_obj,author_obj1]) # 括号内必须给一个可迭代对象
2.4 清空 clear 括号内不要加任何参数 # (4) 清空
#在第三张表中清除某一本书和作者的绑定关系
book_obj models.Book.objects.filter(pk1).first()
# 不要加任何参数
book_obj.authors.clear()
【补充】正反向的概念 正向 外键字段在我手上那么我查你就是正向book 外键字段在书这边(正向) 出版社 反向 外键字段不在我手上那么我查你就是反向出版社 外键字段在书这边(反向) book 一对一和一对多的判断也是这样 正向查询按外键字段 反向查询按表名小写 _set 【八】多表查询
【1】子查询(基于对象的跨表查询)
# [1] 基于对象的跨表查询
# (1)查询书籍主键为1的出版社
book_obj models.Book.objects.filter(pk1).first()
# 书查出版社 - 正向 - 按字段查
res book_obj.publish
print(res) # Publish object
print(res.name) # 东方出版社
print(res.addr) # 东方# (2)查询书籍主键为2的作者
book_obj models.Book.objects.filter(pk1).first()
# 书查作者 - 正向查询按字段
res book_obj.authors
print(res) # app01.Author.None
# 列表中存放的是作者对象
print(res.all()) # QuerySet [Author: Author object]# (3)查询作者 的 电话号码
author_obj models.Author.objects.filter(namedream).first()
# 作者查询作者详情 - 正向查询按字段
res author_obj.author_detail
print(res) # AuthDetail object
print(res.phone) # 110
print(res.addr) # 山东在书写ORM语句的时候跟写SQL语句一样的不要企图一次性将ORM语句写完如果比较复杂需要写一些看一些正向 什么时候需要加 .all()当查询返回的结果是多个的时候就需要用 .all()当查询的结果只有一个的时候就不需要加# (4)查询出版社是东方出版社出版的书
# 先拿到出版社对象
publish_obj models.Publish.objects.filter(name东方出版社).first()
# 出版社查书 - 主键字段在书 - 反向查询
res publish_obj.book_set.all()
# publish_obj.book_set
# print(res) # app01.Book.None
# publish_obj.book_set.all()
print(res) # QuerySet [Book: Book object, Book: Book object, Book: Book object]# (5)查询作者是dream写过的书
# 先拿到作者对象
author_obj models.Author.objects.filter(namedream).first()
# 作者查书 - 主键在书 - 反向
res author_obj.book_set.all()
print(res) # QuerySet [Book: Book object]# (5)查询手机号是 110的作者姓名
# 先拿到作者详情的对象
author_detail_obj models.AuthDetail.objects.filter(phone110).first()
# 详情查作者 - 主键在作者 - 反向
res author_detail_obj.author
print(res) # Author object
print(res.name) # dream基于对象 - 反向查询什么时候需要加 _set.all()查询结果是多个的时候需要加查询结果是多个的时候需要加
【补充】_set.all()(反向查询)
查询结果是多个的时候需要加查询结果是多个的时候需要加
【2】联表查询(基于双下划线的跨表查询)
# [2] 基于双下划线的跨表查询
# (1)查询dream的手机号和作者的姓名
# 正向先查询到作者信息再 .value(需要查询信息的表__需要查询的字段,其他字段)
res models.Author.objects.filter(namedream).values(author_detail__phone, name)
print(res) # QuerySet [{author_detail__phone: 110, name: dream}]
# 反向先拿到详情再用作者详情关联作者表通过 __字段的方法 过滤出我们想要的指定数据
res models.AuthDetail.objects.filter(author__namedream).values(phone, author__name)
# AuthDetail.objects.filter(author__namedream)
print(res) # QuerySet [AuthDetail: AuthDetail object]
# AuthDetail.objects.filter(author__namedream).values(phone,author__name)
print(res) # QuerySet [{phone: 110, author__name: dream}]# (2)查询书籍主键ID为1的出版社名字和书的名字
# 正向先过滤出书籍ID为1的书籍对象再去关联出版者表利用__字段取值
res models.Book.objects.filter(pk1).values(title, publish__name)
print(res) # QuerySet [{title: 三国演义, publish__name: 东方出版社}]
# 反向先查询到指定出版社再从出版社反向找到书籍名字
res models.Publish.objects.filter(book__id1).values(name, book__title)
print(res) # QuerySet [{name: 东方出版社, book__title: 三国演义}]# (3)查询书籍主键ID为1的作者姓名
# 先拿到 书籍主键ID为1的对象再关联作者信息表通过__字段取值
res models.Book.objects.filter(pk1).values(authors__name)
print(res) # QuerySet [{authors__name: dream}]
# 反向 : 先拿到 书籍ID为1的作者数据再去取作者的名字
res models.Author.objects.filter(book__id1).values(name)
print(res) # QuerySet [{name: dream}]# 查询书籍主键是1的作者的手机号
# book author authordetail
res models.Book.objects.filter(pk1).values(authors__author_detail__phone)
print(res) # QuerySet [{authors__author_detail__phone: 110}]只要掌握了正反向的概念以及双下划线查询就可以无限跨表
【九】聚合查询
# 聚合查询# 聚合查询通常情况下都是配合分组一起使用的只要是和数据库相关的模块基本上都在 django.db.models 里面如果这里面没有 那大概率可能在 django.db 里面from django.db.models import Max, Min, Sum, Count, Avg# (1)所有书的平均价格# 正常情况下我们是需要 先进行分组再进行 聚合函数运算的# 但是Django给我们提供了一种方法 aggregate 可以不分组进行某个字段的聚合函数res models.Book.objects.aggregate(Avg(price))print(res) # {price__avg: 1890.083333}# (2)一次性使用res models.Book.objects.aggregate(Avg(price), Max(price), Min(price), Sum(price), Count(pk))print(res) # {price__avg: 1890.083333, price__max: Decimal(5959.25), price__min: Decimal(555.25), price__sum: Decimal(11340.50), pk__count: 6}
【十】分组查询
select age from t group by age;# 分组查询 annotateMySQL分组查询都有哪些特点分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取了严格模式ONLY_FULL_GROUP_BYset global sql_modeONLY_FULL_GROUP_BYfrom django.db.models import Max, Min, Sum, Count, Avg# 1.统计每一本书的作者个数res models.Book.objects.annotate() # models后面点什么 就是按什么分组res models.Book.objects.annotate(author_numCount(authors)).values(title,author_num)author_num是我们自己定义的字段 用来存储统计出来的每本书对应的作者个数res1 models.Book.objects.annotate(author_numCount(authors__id)).values(title,author_num)print(res,res1)代码没有补全 不要怕 正常写补全给你是pycharm给你的 到后面在服务器上直接书写代码 什么补全都没有 颜色提示也没有# 2.统计每个出版社卖的最便宜的书的价格(作业:复习原生SQL语句 写出来)res models.Publish.objects.annotate(min_priceMin(book__price)).values(name,min_price)print(res)# 3.统计不止一个作者的图书# 1.先按照图书分组 求每一本书对应的作者个数# 2.过滤出不止一个作者的图书res models.Book.objects.annotate(author_numCount(authors)).filter(author_num__gt1).values(title,author_num)只要你的orm语句得出的结果还是一个queryset对象那么它就可以继续无限制的点queryset对象封装的方法print(res)# 4.查询每个作者出的书的总价格res models.Author.objects.annotate(sum_priceSum(book__price)).values(name,sum_price)print(res)如果我想按照指定的字段分组该如何处理呢models.Book.objects.values(price).annotate()后续BBS作业会使用你们的机器上如果出现分组查询报错的情况你需要修改数据库严格模式
【十一】F与Q查询
【1】F查询
# F查询# 1.查询卖出数大于库存数的书籍# F查询能够帮助你直接获取到表中某个字段对应的数据from django.db.models import Fres models.Book.objects.filter(maichu__gtF(kucun))print(res)# 2.将所有书籍的价格提升500块models.Book.objects.update(priceF(price) 500)# 3.将所有书的名称后面加上爆款两个字在操作字符类型的数据的时候 F不能够直接做到字符串的拼接from django.db.models.functions import Concatfrom django.db.models import Valuemodels.Book.objects.update(titleConcat(F(title), Value(爆款)))models.Book.objects.update(titleF(title) 爆款) # 所有的名称会全部变成空白
【2】Q查询 # Q查询# 1.查询卖出数大于100或者价格小于600的书籍res models.Book.objects.filter(maichu__gt100,price__lt600)filter括号内多个参数是and关系from django.db.models import Qres models.Book.objects.filter(Q(maichu__gt100),Q(price__lt600)) # Q包裹逗号分割 还是and关系res models.Book.objects.filter(Q(maichu__gt100)|Q(price__lt600)) # | or关系res models.Book.objects.filter(~Q(maichu__gt100)|Q(price__lt600)) # ~ not关系print(res) # QuerySet []# Q的高阶用法 能够将查询条件的左边也变成字符串的形式q Q()q.connector orq.children.append((maichu__gt,100))q.children.append((price__lt,600))res models.Book.objects.filter(q) # 默认还是and关系print(res)