首页 笔记正文

【笔记】Django模型层

從出茳湖 笔记 2019-09-19 86 0


ORM单表操作

单表操作演示表

class Book(models.Model):
  	name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_place=2)
    publish = models.CharField(max_length=32)
    author = models.CharField(max_length=32)
    create_time = models.DateField(null=True)
    # 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    # 配置上auto_now=True,每次更新数据记录的时候会更新该字段。

新增数据

# 第一种:有返回值,并且就是当前被创建的数据对象
modles.Book.objects.create(name='',price='',publish='',author='',create_time='2019-5-1')
# 第二种:先实例化产生对象,然后调用save方法保存
book_obj = models.Book(name='',price='',publish='',author='',create_time='2019-5-1')
book_obj.save()
# 2.验证时间格式字段即可以传字符串也可以传时间对象
import datetime
ctime = datetime.datetime.now()
book = models.Book.objects.create(name='',price='',author='',create_time=ctime)

删除数据

"""删除数据"""
# 1.删除书名为xxx的这本书  queryset方法
res = models.Book.objects.filter(name='').delete()
print(res)
# 2.删除书名为xxx的这本书  queryset方法
res = models.Book.objects.filter(name='').first()
res.delete()

修改数据

# 1.queryset修改
models.Book.objects.filter(name='').update(price='')
# 2.对象修改
book = models.Book.objects.filter(name='').first()
book.price = 66.66
book.save()  # 对象只有保存方法 这样也能实现修改需求

查询数据的13个方法

返回QuerySet对象的方法有:

all()            查询所有结果

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

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

order_by() 对查询结果排序

reverse()    对查询结果反向排序>>>前提是要先有排序才能反向

distinct()    从返回结果中剔除重复记录(必须是完全相同的两条记录)

特殊的QuerySet:

values()           返回一个可迭代的字典序列

values_list()     返回一个可迭代的元组序列

返回具体对象的:

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

first()    返回第一条记录

last()    返回最后一条记录

返回布尔值的方法有:

exists()    如果QuerySet包含数据,就返回True,否则返回False

返回数字的方法有:

count()    返回数据库中匹配查询

查看orm内部sql语句的方法有哪些

1.如果是queryset对象,那么可以点query直接查看该queryset的内部sql语句

2.在Django项目的配置文件中,配置以下参数即可实现所有的orm在查询的时候自动打印对应的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',
        },
    }
}

神奇的双下划线查询

# 价格 大于 小于 大于等于 小于等于
filter(price__gt='90')
filter(price__lt='90')
filter(price_gte='90')
filter(price_lte='90')

# 存在与某几个条件中
filter(price__in=['11','22','33'])

# 在某个范围内
filter(price__range=[50,90])

# 模糊查询
filter(title__contains='西')
filter(title__icontains='P')

# 以什么开头 以什么结尾
filter(title__startswith='三')
filter(title__endswith='p')

# 按年查询
filter(create_time__year='2017')

多表操作

一对一查询,一对一关联其实就是外健关联再加一个唯一性约束

ForeignKey(unique=Ture)		>>>		OneToOneField()		
# 即一对一可以用ForeignKey来做,但是需要设唯一性约束并且会报警告信息,不建议使用,建议用OneToOneField
# 用了OneToOneField和用ForeignKey会自动在字段后面加_id
# 用了ManyToMany会自动创建第三张表

一对多增删改查

# 增:针对外键关联的字段 两种添加方式
    # 第一种通过publish_id
    models.Book.objects.create(publish_id=1,)
    # 第二种通过publish传出版社对象
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(publish=publish_obj,)
    
# 删:删除书籍直接查询删除即可,删除出版社会级联删除
    models.Publish.objects.filter(pk=2).delete()  # 默认都是级联更新 级联删除

# 改:编辑数据也是两种对应的方式(对象点的方式(这里能点publish和publish_id)最后点save(),queryset方式update())
    # 传数字的
    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)

多对多增删改查

"""前提:先获取书籍对象,再通过书籍对象点authors来进行书籍作者的增删改查"""
# 增:给书籍新增作者add
    # add可以传作者id,也可以直接传作者对象,并且支持传多个位置参数(不要混着用)
  
# 删:给书籍删除作者remove
    # remove同样可以传id,对象,并且支持传多个位置参数(不要混着用)

# 清空:直接清空书籍对象所有的作者数据
    # clear()不用传任何参数

# 改修改书籍对象所关联的作者信息set,注意点set括号内必须传可迭代对象,里面可以传id,对象
	
"""总结:一对多增删改,多对多add,remove,clear,set"""
create() 创建一个关联对象,并自动写入数据库,且在第三张双方的关联表中自动新建上双方对应关系。
add()    把指定的model对象添加到第三张关联表中。
set()    更新某个对象在第三张表中的关联对象。不同于上面的add是添加,set相当于重置
remove() 从关联对象集中移除执行的model对象(移除对象在第三张表中与某个关联对象的关系)
clear()  从关联对象集中移除一切对象。(移除所有与对象相关的关系信息)
"""
注意:1.对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
      2.对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。
"""

正向反向查找

# 正向与方向的概念解释

# 一对一
# 正向:author---关联字段在author表里--->authordetail	按字段
# 反向:authordetail---关联字段在author表里--->author	按表名小写
	# 查询jason作者的手机号       正向查询
	# 查询地址是 :山东 的作者名字 反向查询
  
# 一对多
# 正向:book---关联字段在book表里--->publish	按字段
# 反向:publish---关联字段在book表里--->book	按表名小写_set.all() 因为一个出版社对应着多个图书

# 多对多
# 正向:book---关联字段在book表里--->author	按字段
# 反向:author---关联字段在book表里--->book	按表名小写_set.all() 因为一个作者对应着多个图书
# 连续跨表
    # 查询图书是三国演义的作者的手机号,先查书,再正向查到作者,在正向查手机号
"""基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)"""

多表查询

# 1.查询书籍id是1 的出版社名称
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name)
2.查询书籍id是2 的作者姓名
book_obj = models.Book.objects.filter(pk=2).first()
# print(book_obj.authors)  # app01.Author.None
print(book_obj.authors.all())
res = book_obj.authors.all()
for r in res:
    print(r.name)
# 3.查询作者是jason的家庭住址
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.author_detail.addr)
# 4.查询出版社是东方出版社出版的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set.all())
# 5.查询作者是jason的写过的所有的书籍
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set.all())
# 6.查询电话号码是130的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
print(author_detail_obj.author.name)
"""
当你反向查询的结果是多个的时候 就需要加_set
否则直接表明小写即可
"""
# 7.查询书籍id为1 的作者的电话号码
book_obj = models.Book.objects.filter(pk=1).first()
author_list = book_obj.authors.all()
for author_obj in author_list:
    print(author_obj.author_detail.phone)

基于双下划线的跨表查询

"""基于双下划线的跨表查询(连表操作)
-连表查询
-一对一双下划线查询
-正向:按字段,跨表可以在filter,也可以在values中
-反向:按表名小写,跨表可以在filter,也可以在values中
"""
# 查询jason作者的手机号   正向查询  跨表的话,按字段
# ret=Author.objects.filter(name='jason').values('authordetail__phone')
# 以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写
# ret=AuthorDetail.objects.filter(author__name='jason').values('phone')
    
# 查询jason这个作者的性别和手机号
# 正向
# ret=Author.objects.filter(name='jason').values('sex','authordetail__phone')

# 查询手机号是13888888的作者性别
# ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
# ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
    
"""
总结 其实你在查询的时候先把orm查询语句写出来,再看用到的条件是否在当前表内,在就直接获取,不在就按照正向按字段反向按表名来查即可
比如:
	1.查询出版社为北方出版社的所有图书的名字和价格
	res1 = Publish.objects.filter(name='').values('book__name','book__price')
	res2 = Book.objects.filter(publish__name='').values('name','price')
	2.查询北方出版社出版的价格大于19的书
	res1 = Publish.objects.filter(name='',book__price__gt=19).values('book__name','book__price)
"""

聚合查询(aggregate)

# 1.统计所有书的总价格
from django.db.models import Max,Min,Count,Avg,Sum

res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))
print(res,res1,res2,res3,res4,res5)

分组查询

# 统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
print(res)
# 统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
print(res)

# 统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
print(res)

"""
只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选

"""

# 查询各个作者出的书的总价格
res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
print(res)

F查询

#F查询的本质就是从数据库中获取某个字段的值
# 查询库存数大于卖出数的书籍
"""之前查询等号后面的条件都是我们认为输入的
    现在变成了需要从数据库中获取数据放在等号后面
"""
from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu'))
print(res)


# 将书籍库存数全部增加1000
models.Book.objects.update(kucun=F('kucun')+1000)

# 把所有书名后面加上'新款'

from django.db.models.functions import Concat
from django.db.models import Value

res = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
# models.Book.objects.update(title = F('title')+'新款')  # 不能这么写

Q查询

from django.db.models import Q
# 查询书籍名称是三国演义或者价格是444.44
res = models.Book.objects.filter(title='三国演义',price=444.44)  # filter只支持and关系
res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444))  # 如果用逗号 那么还是and关系
res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))
res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))
print(res)


# Q高级用法
q = Q()
q.connector = 'or'  # 修改查询条件的关系   默认是and
q.children.append(('title__contains','三国演义'))  # 往列表中添加筛选条件
q.children.append(('price__gt',444))  # 往列表中添加筛选条件
res = models.Book.objects.filter(q)  # filter支持你直接传q对象  但是默认还是and关系
print(res)

本文标题:【笔记】Django模型层
本文链接:https://zhong-er.com/post/81.html
作者授权:除特别说明外,本文由 從出茳湖 原创编译并授权 中二青年 刊载发布。
版权声明:本文使用「署名-非商业性使用-相同方式共享 4.0 国际」创作共享协议,转载或使用请遵守署名协议。

评论

本站会员尊享VIP特权,现在就加入我们吧!登录注册
登录
用户名
密码
注册
用户名
密码
确认密码
邮箱
获取邀请码
邀请码
验证码
找回密码
用户名
邮箱
※ 重置链接将发送到邮箱