测试环境
import osif __name__ == "__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")import djangodjango.setup()下面继续书写脚本代码
前识回顾:
import osif __name__ == "__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")import djangodjango.setup()from app91 import modelsimport 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__namemodels.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,Avgfrom app91 import modelsmodels.Book.objects.aggregate(Avg('price'),Max('price'),Min('price'),Count('pk'),Sum('price'))
分组查询
分组查询 annotatemodels.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 Fmodels.Book.objects.filter(salesnum__gt=F('inventory')) 查询销售数量大于库存数量的书籍models.Book.objects.update(price=F('price')+10) 给书籍表中所有书籍价格加10Q查询from django.db.models import Qmodels.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 transactionwith transaction.atomic():sql1sql2sql3.....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为字段名如果没有对应关系则直接返回存储的值
