Django ORM参数与操作
Django ORM常用字段和参数
常用字段
AutoField
int自增列,必须填入参数primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列
IntegerField
一个整数类型,范围在-2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存。)
CharField
字符类型,必须提供max_length参数,max_length表示字符长度
DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM:SS,相当于Python中的datetime.datetime()实例。
字段参数
null
用于表示某个字段可以为空。
unique
如果设置为unique=True 则该字段在此表中必须是唯一的 。
db_index
如果db_index=True 则代表着为此字段设置索引。
default
为该字段设置默认值。
auto_now
每次操作改数据都会自动更新时间
auto_now_add
新增数据的时候会将当前时间自动添加,后续的修改该字段不会自动更新
单独的py文件测试ORM操作需要配置的参数
# 可以在manage.py文件中复制
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE","day58.settings")
import django
django.setup()
from app01 import models # 这一句话必须在这下面导入

单表查询
查询方法
all( ):查询所有结果

filter(kwargs):包含了与所给筛选条件相匹配的对象

get(kwargs):返回了所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

exclude(kwargs):包含了与所给筛选条件不匹配的对象

order_by(*field):对查询结果排序
reverse():对查询结果反向排序 >>> 要先有排序才能反向
count():返回数据库中匹配查询

first():返回第一条记录

last():返回最后一条记录
exists():若果QuerySet包含数据,就返回True,否则返回False
values(*field):返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列

values_list(*field):它与values()非常相似,它返回的是一个元组序列

distinct():从返回结果中剔除重复纪录
查询方法总结
返回QuertSet对象的方法有
all()
filter()
exclude()
order_by()
reverse()
distinct()
特殊的QuerySet
values():返回一个可迭代的字典序列
values_list:返回一个可迭代的元组序列
返回具体对象
get()
first()
last()
返回布尔值的方法
exists()
返回数字的方法
count()
Django终端打印SQL语句
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上
单表查询之神奇的双下划綫
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains忽略大小写
models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and
res = models.User.objects.filter(name__startswith='j') # 查询名字以j开头的用户
res = models.User.objects.filter(name__endswith='n') # 查询名字以n结尾的用户
# date字段还可以:
models.Class.objects.filter(first_day__year=2017)
# date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据
多表查询
表与表之间的关系
一对一(OneToOneField)
一对一字段无论建在哪张关系表里面都可以,但是推荐建在查询频率比较高的那张表里面
一对多(Foreignkey)
一对多字段建在多的那一方
多对多(ManyToManyField)
多对多字段无论建在哪张关系表里面都可以,但是推荐建在查询频率比较高的那张表里面
多表查询方法
新增
# 直接写id
models.Book.objects.create(title='红楼梦',prrice=66.66,publish_id=1)
# 传数据对象
publish_obj = model.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='三国演义',price=199.99,publish=publish_obj)
修改
# queryset修改
models.Book.objects.filter(pk=1).update(publish_id=3)
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
# 对象修改
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.publish_id = 3 # 点表中真实存在的字段名
book_obj.save()
publish_obj = models.Publish.objects.filter(pk=2).first()
book_obj.publish = publish_obj # 点orm中字段名 传该字段对应的表的数据对象
book_obj.save()
删除
# queryset删除
models.Book.objects.filter(pk=1).delete()
models.Publish.objects.filter(pk=1).delete()
# 对象删除
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.delete()
多对多表操作
添加绑定关系(add( ):add支持传数字或对象,并且都可以传多个值)
# 例如给书籍绑定与作者之间的关系
# 通过id添加
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.add(1)
book_obj.authors.add(2,3)
# 通过对象添加
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=3).first()
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj,author_obj1)
修改绑定关系(set( ):set传的必须是可迭代对象)
book_obj = models.Book.objects.filter(pk=3).first()
# 通过id修改
book_obj.authors.set((1,))
# 支持传多个
book_obj.authors.set((1,2,3))
# 通过对象修改
author_list = models.Author.objects.all()
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.set(author_list)
删除绑定关系(remove( ))
book_obj = models.Book.objects.filter(pk=3).first()
# 通过id删除
book_obj.authors.remove(1)
book_obj.authors.remove(2,3)
# 通过对象删除
author_obj = models.Author.objects.all().first()
author_list = models.Author.objects.all()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(*author_list) # 需要将queryset打散
清空绑定关系(clear( ):清空当前表记录对应的绑定关系)
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.clear()
正反向操作
# 正向与方向的概念解释
# 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写
# 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书
# 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书
# 连续跨表
# 查询图书是三国演义的作者的手机号,先查书,再正向查到作者,在正向查手机号
# 总结:基于对象的查询都是子查询,这里可以用django配置文件自动打印sql语句的配置做演示
基于对象的表查询
正向
# 查询书籍是三国演义的出版社邮箱
book_obj = models.Book.objects.filter(title='三国演义').first()
print(book_obj.publish.email)
# 查询书籍是水浒传的作者的姓名
book_obj = models.Book.objects.filter(title='水浒传').first
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all())
# 查询作者为jason电话号码
user_obj = models.Author.objects.filter(name='jason').first()
print(user_obj.phone)
反向
# 查询出版社是东方出版社出版的书籍 一对多字段的反向查询
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all())
# 查询作者jason写过的所有的书 多对多字段的反向查询
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all())
# 查询作者电话号码是110的作者姓名 一对一字段的反向查询
authordetail_obj = models.AuthorDetail.objects.filter(phone=110).first()
print(authordetail_obj.author.name)
基于双下划线的查询
正向
# 查询书籍为三国演义的出版社地址
models.Book.objects.filter(title='三国演义').values('publish__addr','title')
# 查询书籍为水浒传的作者的姓名
models.Book.objects.filter(title='水浒传').values('authors__name','title')
# 查询作者为jason的家乡
model.Author.object.filter(name='jason').values('authordetail__addr')
反向
# 查询南方出版社出版的书名
models.Publish.objects.filter(name='南方出版社').values('book__title')
# 查询电话号码为120的作者姓名
models.AuthorDetail.objects.filter(phone=120).values('author__name')
# 查询作者为jason的写的书的名字
models.Author.object.filter(name='jason').values('book__title')
# 查询书籍为三国演义的作者的电话号码
models.Book.objects.filter(title='三国演义').values('authors__authordetail__phone')
聚合查询(aggregate)
from django.db.models import Max,Min,Count,Sum,Avg
# 查询id为3书籍的作者个数
models.Book.object.filter(pk=3).aggregate(count_num=Count('authors'))
# 查询所有出版社出版的书的平均价格
models.Publish.object.aggregate(avg_price=Avg('book__price'))
# 统计东方出版社出版的书籍的个数
models.Publish.object.filter(name='东方出版社').aggregate(count_num=Count('book__id'))
分组查询 (annotate)
from django.db.models import Max,Min,Count,Sum,Avg
# 统计每个出版社出版的书的平均价格
models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name','avg_price')
# 统计每一本书的作者个数
models.Book.objects.annotate(count_num=Count('authors')).values('title','count_num')
# 统计出每个出版社卖的最便宜的书的价格
models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
# 查询每个作者出的书的总价格
models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')

浙公网安备 33010602011771号