测试环境
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")
import django
django.setup()
下面继续书写脚本代码
前识回顾:
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")
import django
django.setup()
from app91 import models
import datetime
#增
# 方式一
# models.User.objects.create(name='wyy',age=19,register_time='2021-2-8 8:00:00')
#方式二
# user_obj = models.User(name='lili',age=56,register_time=datetime.datetime.now())
# user_obj.save()
# 删
# 方式一
# models.User.objects.filter(pk =1).delete()
# 方式二
# user_obj = models.User.objects.filter(pk = 1).first()
# user_obj.delete()
# 改
# 方式一
# models.User.objects.filter(pk = 1).update(name='lala')
# 方式二
# user_obj = models.User.objects.get(pk = 1) #该方法不推荐使用,如果pk不存在则会直接报错,而filter则不会
# user_obj.name = 'heihei'
# user_obj.save()
查看内部sql语句的方式
.query 只能用于queryset
通用方式:在配置内加配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
必会13条
# 1.all() 查询所有
# 2.filter 带有过滤条件的查询
# 3.get 直接拿数据对象,条件不存在时直接报错
# 4.first 拿queryset内第一个元素
# 5.last 拿queryset内最后一个元素
# 6.values 拿取一个或多个字段对应的值
# models.User.objects.values('name','age')
# 类似于 select name,age from ...;
#返回的是[{},{}]
# 7.values_list
# models.User.objects.values_list()
#返回的是[(),()]
# 8.distinct 去重,要把主键排除在外,否则无法去重
# models.User.objects.values('name','age').distinct()
# 9.order_by 排序
# models.User.objects.order_by('age') #默认升序
# models.User.objects.order_by('-age') #降序
# 10.reverse 反转的前提是数据已经排序
# 11.count 统计个数
#models.User.objects.all().count()
# 12.exclude 排除某个在外
# models.User.objects.exclude(name='wyy')
# 13.exists 判断是否存在
双下划线查询
# models.User.objects.filter(age__gt=20) 大于
# models.User.objects.filter(age__lt=20) 小于
# models.User.objects.filter(age__lte=20) 小于等于
# models.User.objects.filter(age__gte=20) 大于等于
# models.User.objects.filter(age__in=[10,20,30]) 查询年龄是10,20,30的数据
# models.User.objects.filter(age__range=[10,30]) 查询年龄在10-30之间的数据,收尾兼顾
# models.User.objects.filter(name__contains='n') 查询名字包含n的数据 区分大小写
# models.User.objects.filter(name__icontains='n') 查询名字包含n的数据 忽略大小写
# models.User.objects.filter(name__endswith='w') 查询名字以w结尾的数据,startwith同理
# models.User.objects.filter(register_time__year='2021') 查询时间以年份为单位查询,月、日.....同理
外键增删改查
#外建增删改查
# 一对多
# 增
# models.Book.objects.create(titlle='',price='',publish_id=值)
# models.Book.objects.create(titlle='',price='',publish=对象)
# 删
# models.Publish.objects.filter().delete() 级联删除
# 修改
# 修改一样可以和增加一样直接给值或者给对象
# 多对多 第三张关系表的增删改查
# 增
# 书籍表和作者表
# Book_obj = models.Book.objects.filter(pk=1).first()
#
# Book_obj.authors.add(1,2) 主键为1的书籍添加作者主键为1和2,以此操作第三张表
#
# author_obj = models.author.objects.filter(pk= 1).first()
# Book_obj.authors.add(author_obj) 对象可放多个
#
# add:给第三张关系表添加数据,括号内既可以传值,也可以传对象,支持多个
#
#
#
#
# 删
#
# Book_obj.authors.remove(1,2) 同样支持传值和对象
#
# remove 第三张关系表删除数据,括号内既可以传值,也可以传对象,支持多个
#
#
# 改
#
# Book_obj.authors.set([1,2])
#
# set 括号内必须是可迭代对象,既可以是对象也可以是值,同样支持多个
# 先删除,后新增的方式修改
#
#
# 清空
#
# 在第三张表内清空两者绑定关系
#
# Book_obj.authors.clear() 清空Book_obj绑定的所有关系
正反向的跨表查询
正反向概念
看外键字段在哪张表,有外键字段查询没有外键字段的,为正向,反之则为反向
正向查询按字段
反向查询按表名小写
跨表查询
基于对象(子查询)
正向
查询书籍主键为1的出版社
Book_obj = models.book.objects.filter(pk=1).first()
Book_obj.publish.all().name 获取出版社名字 能拿到多个,则要.all()
Book_obj.publish.addr 获取出版社地址
反向
查询出版社出版了哪些书
publish_obj = models.Publish.objects.filter(name='北京出版社').first()
publish_obj.book_set.all()
总结:
当反向查询结果有多个需要在表名后加_set.all(),一个则不需要
基于双下划线(联表查询)
查询书籍主键为1的出版社名称和书的名称
models.book.objects.filter(pk =1).values('title','publish__name')
title 在book表内直接写,出版社名称在另外一张表,直接publish__name
models.Publish.objects.filter(book__id=1).values('name','book__title')
上述正反向结果一致
查询书籍主键为1的作者的电话号码
models.Book.objects.filter(pk=1).values('author__author_detail__phone')
聚合查询
# 聚合查询 aggregate(单独使用的时候用的关键字)
from django.db.models import Min,Max,Sum,Count,Avg
from app91 import models
models.Book.objects.aggregate(Avg('price'),Max('price'),Min('price'),Count('pk'),Sum('price'))
分组查询
分组查询 annotate
models.Book.objects.annotate() 按书分组
models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
models.Book.objects.values('price').annotate() 按照表中指定字段进行分组
分组查询如果出错,记得查看严格模式
F与Q查询
F查询
from django.db.models import F
models.Book.objects.filter(salesnum__gt=F('inventory')) 查询销售数量大于库存数量的书籍
models.Book.objects.update(price=F('price')+10) 给书籍表中所有书籍价格加10
Q查询
from django.db.models import Q
models.Book.objects.filter(Q(salesnum__gt=100),Q(price__gt=20)) 默认and关系
models.Book.objects.filter(Q(salesnum__gt=100)|Q(price__gt=20)) or关系
models.Book.objects.filter(~Q(salesnum__gt=100)|Q(price__gt=20)) 非关系
Q高阶用法
q=Q()
q.connector='or' 改成or连接
q.children.append('salenum__gt',100)
q.children.append('price__gt',20)
models.Book.objects.filter(q) 等同于上面的and关系查询
django中开启事务
from django.db import transaction
with transaction.atomic():
sql1
sql2
sql3.....
with下书写的sql都属于同一个事务
choices参数
# choices参数
# 只要某个字段可能性能列举完全的,一般情况下都会采用choices参数
#
class User(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
gender_choices =(
(1,'男'),
(2,'女'),
(3,'其他'),
)
gender = models.IntegerField(choices=gender_choices)
#gender中存到数字在上面的gender_choices中,会自动匹配到对应关系
#不在范围内照样存储
models.User.objects.filter(pk=1).first().get_gender_display()
取值方法:get_XXX_display() XXX为字段名
如果没有对应关系则直接返回存储的值