标签:函数 any 默认 帮助 级联 虚拟 sel nta lte
class User(models.Model)
name = models.CharField(max_length)
age = models.InterField()
register_time = models.DateField() ## models.DateTimeField()
针对DateField以及DateTimeField,有两个关键参数
1.auto_now:每次操作数据的时候,该字段会自动将该字段时间更新
2.auto_now_add:在创建数据的时候会自动将当前创建时间记录下来,之后只要不任伟的修改,就不会改变
python manage.py makemigrations
python manage.py migrate
res = models.User.objects.create(name=‘lilli‘,age=18,register_time=‘2021/1/5‘)
user_obj = models.User(name=‘‘,age=,register_time)
user_obj.save()
pk会自动查找到当前表的主键字段,指代的就是当前表的主键
res = models.User.objects.filter(pk=2).delete()
user_obj = models.User.objects.filter(pk=1).first().delete()
get方法返回的就是当前数据对象,但是该方法不推荐使用,一旦数据不存在,该方法会直接报错
filter不会报错,而会返回一个空
models.User.objects.filter(pk=4).update()
user_obj = models.User.objects.get(pk=4)
user_obj.name = ‘‘
1.all() # 查询所有
2.filter() # 带有过滤条件的查询
3.get() # 直接拿数据对象,但是条件不存在直接报错
4.first() # 拿queryset里面第一个元素
5.last() # 拿queryset里面最后一个元素
6.values() # 可以指定获取的数据字段 select name,age from ...
res = models.User.objects.values(‘name‘,‘age‘) # 可以看成列表套字典
7.values_list() # 可以指定获取的数据字段
res = models.User.objects.values_list(‘name‘) # 可以看成列表套元组
res.query # 查看内部封装的sql语句,上述查看sql语句的方式,只能用于queryset对象,只有queryset对象才能够点击query查看内部的sql语句
8.distinct() # 去重,一定要一摸一样的数据,如果带有主键,那么肯定不一样,查询一定不要忽略主键
res = 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() # 统计当前数据的个数
res = models.User.objects.count()
12.exclude() # 排除什么在外
res = models.User.objects.exclude(name=‘lili‘)
13.exists() # 判断对象是否存在,返回的是布尔值
res = models.User.objects.filter(pk=3).exists()
# 查询年龄大于35岁的数据
res = models.User.objects.filter(age__gt=35)
# 小于35
res = models.User.objects.filter(age__lt=35)
# 大于等于
res = models.User.objects.filter(age__gte=35)
# 小于等于
res = models.User.objects.filter(age__lte=32)
# 查询年龄18或者32或者40
res = models.User.objects.filter(age__in=[18,32,40])
# 年龄在18~40之间
res = models.User.objects.filter(age__range=[18,40]) # 首尾兼顾
# 查询出名字里含有n的数据,模糊查询
res = models.User.objects.filter(name__contains=‘n‘)
# 那么是否区分大小写呢?
# 默认是区分大小写的
res = models.User.objects.filter(name__icontains=‘p‘) # 忽略大小写
# 以啥开头,结尾
res = models.User.objects.filter(name__startwith=‘j‘)
# 查询出注册时间2020年1月份的数据,按照年月日拿数据
res = models.User.objects.filter(register_time__month=‘1‘)
res = models.User.objects.filter(register_time__year=‘2020‘)
res = models.User.objects.filter(register_time__day=‘1‘)
# 一对多的外键增删改查
## 增
1.直接写实际字段 id
models.Book.object.create(title=‘三国‘,price=123.23,publish_id=1)
2.虚拟字段 对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title=‘红楼‘,price=1111.11,publish=publish_obj)
## 删,默认级联的
models.Publish.objects.filter(pk=1).delete()
## 修改,也可以传对象或者id
models.Book.objects.filter(pk=1).update(publish_id=2)
# 多对多的增删改查(就是在操作第三张关系表)
## 如何给书籍添加作者?
book_obj = models.objects.filter(pk=1).first()
book_obj.authors # 就类似于已经到了第三张关系表了
book_obj.authors.add(1) # 给书籍id为1的书籍绑定一个主键值为1的作者
book_obj.authors.add(2,3) # 可以添加多个对应值
author_obj = models.objects.filter(pk=1).first()
book_obj.authors.add(author_obj) # 还可以直接添加对象
"""
add给第三张关系表添加数据,既可以传对象,也可以传值
"""
## 删除
book_obj.authors.remove(2,3)
book_obj.authors.remove(author_obj)
"""
remove既可以传值,也可以传对象,并且也支持多个
"""
## 修改(set)
book_obj.authors.set([1,3]) # 括号内必须为可迭代对象
book_obj.authors.set([3,])
book_obj.authors.set([author_obj,author_obj1])
"""
set即可以传数字,也可以传对象,但必须在可迭代对象内
先删除,后新增
"""
## 清空,在第三张关系表中清空某个书籍与作者的绑定关系
book_obj.authors.clear()
"""
clear不需要加任何参数
"""
"""
正向:看外键字段在谁那儿,有谁开始查询,就是正向,外键字段如果不再我这,那么有我查你,就是反向
"""
"""
正向查询按字段
反向查询按表名小写
_set
...
"""
# 子查询(基于对象的跨表查询)
查询书籍主键为1的出版社
book_obj = models.Book.objects.filter(pl=1).first()
书查出版社,正向
publish_obj = book_obj.publish
publish_obj.name
查询书籍主键为1的作者,正向
book_obj.authors # app01.Author.None
book_obj.authors.all() # 拿到作者对象
查询作者jason的电话号码,正向
author_obj.author_detail.phone
"""
在书写ORM语句的时候和写sql一样,不要一次写完,一步一步来
正向查询结果如果为多个的时候需要加.all(),拿对象
"""
查询东方出版社出版的书,反向
publish_obj
publish_obj.book_set.all() # 拿到出版社对应的所有的相关的书
查询作者是jason写过的书,反向
author_obj
author_obj.book_set.all() # 拿到作者对应的相关的所有的书
查询手机号为110的作者姓名
author_detail_obj.author() # 直接拿到对应的作者
"""
反向查询
当你的查询结果可以有多个的时候,必须加_set.all()
只有一个的时候,不需要加
"""
# 正向
查询jason的手机号,正向
res = models.Author.objects.filter(name=‘jason‘).values(‘author_detail__phone‘)
查询书籍主键为1的出版社名称和书的名称,正向
res = models.Book.objects.filter(pk=1).values(‘title‘,‘publish__name‘)
查询书籍主键为1的作者姓名
res = models.Book.objects.filter(pk=1).values(‘author__name‘)
# 反向
models.AuthorDetail.objects.filter(author__name=‘jason‘).values(‘phone‘,‘author__name‘) 拿作者姓名是jsaon的作者详情
models.Publish.objects.filter(book__id=1).values(‘name‘,‘book__title‘)
models.Author.objects.filter(book_id=1).values(‘name‘)
# 查询书籍主键是1的作者的手机号
models.Book.objects.filter(pk=1).values(‘author__author_detail__phone‘)
"""
只要掌握了正反向的概念,以及双下划线,你就可以无限制跨表查询
"""
先导入,只要和数据库相关的都在django.db.models里面,或者django.db
如果不想聚合,需要aggregate
from django.db.models import Max,Min,Sum,Count,Avg
models.Book.objects.aggregate(Avg(‘price‘))
models.Book.objects.aggregate(Max(‘price‘),Min(‘price‘))
关键字:annotate
"""
Mysql分组之后,默认只能获取到分组的依据,组内其他字段都无法直接截取了,严格模式 ONLY_FULL_GROUP
"""
"""
ORM分组,关键字annotate
"""
统计每一本书的作者个数 ------->按书来分组
models.Book.objects.annotate() # models后面点什么就是按照什么分组
models.Book.objects.annotate(author_num=Count(‘authors‘)).values(‘title‘,‘author_num‘)
统计每个出版社卖的最便宜的书的价格
models.Publish.objects.annotate(book_price = Min(‘book__price‘)).values(‘name‘,‘book__title‘,‘book_price‘)
统计不止一个作者的图书
models.Book.objects.annotate(author_num = Count(‘author‘)).filter(‘author_num‘__gt=1).values(‘title‘,‘author_num‘)
"""
只要你的ORM语句得出的结果还是一个queryset对象
那么他就可以继续无限制的点queryset对象封装的方法
"""
查询每个作者出的书的总价格
models.Author.objects.annotate(sum_price = Sum(‘book__price‘)).values(‘name‘,‘sum_price‘)
"""
如何按照指定的字段分组?
models.Book.objects.values(‘price‘).annotate()
如果查询分组查询报错的情况,你需要修改数据库严格模式,ONLY_FULL_GROUPBY
"""
F的功能可以帮助你直接获取列表中某个字段对应的数据
for循环取值的意思吗
查询卖出数量大于库存数量的书籍
from django.db.models import F
models.Book.objects.filter(maichu__gt=F(‘kucun‘))
将所有书的价格提升50块
models.Book.objects.filter(price = F(‘price‘) + 50)
将所有书的名称后面加上爆款两个字
"""
在操作字符类型的数据的时候,F不能够直接做到字符串的拼接
"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.object.update(title=Concat(F(‘title‘),Value(‘爆款‘)))
# Q的功能可以
查询卖出数大于100或者价格小于600的书籍
from django.db.models import Q
models.Book.objects.filter(Q(maichu__ge=100|price__lt=600)) # Q包裹,逗号分隔还是and关系;|是or关系;~是非关系
"""
filter括号内多个参数是and关系
"""
# Q的高阶用法,能够将查询条件的左边也变成字符串的形式
q = Q()
q.connector = ‘or‘ # 将方式由and改成or
q.children.append((‘maichu__gt‘,100))
q.children.append((‘price__lt‘,600))
models.Book.objects.filter(q) # 默认还是and关系
"""
事务:acid(原子性、一致性、隔离性、持久性)
"""
# 如何简单的开启事务
from django.db import transaction
with transaction.atomic():
# sql语句
# 在with内书写代码块内书写的所有ORM操作都属于统一个事务
AutoField:主键字段,primary_key=True必须指定
CharField:字符串,verbose_name(字段注释),max_length(字段长度)
IntegerField:int
DecimalField:max_digits,decimal_places
EmailField:varchar(254)
DateField:auto_now(每次修改数据的时候都会更新),auto_now_add(只在创建的时候记录,之后不会修改了)
BoolenaField:布尔值类型
"""
改字段传布尔值,数据库里面存0或1
"""
TextField:文本类型
"""
该字段可以用来存大段内容(文章、博客……),没有字数限制
"""
FileField:文件类型(字符类型)
"""
upload_to=‘/data‘ 给该字段传一个文件对象,会自动将文件保存到/data目录下,然后将路径保存到路径中
"""
# 更多字段
参考博客
Dominic-Ji
# django除了提供了很多字段类型之外,还支持自定义字段
class MyCharField(models.Field):
def __init__(self,max_length,*args,**kwargs):
self.max_length = max_length
super().__init__(max_length=max_length,*args,**kwargs)
def db_type(self,connection):
return ‘char({})‘.format(self.max_length)
myfield = MyCharField(max_length=10)
# 参数
unique = True
ForeignKey(unique = True) ==== OneToOneField() # 在用ORM创建的时候会有一个提示信息
db_index = True # 代表为此字段设置索引
to_field = ‘‘ # 设置需要关联的字段,默认不写就是关联另外一张的主键字段
on_delete # 级联行为
only与defer
"""
ORM语句的特点:
惰性查询:如果仅仅只是书写了ORM语句,后面根本没有用到该语句所查询出来的参数,那么ORM会自动识别,只有使用到了才会走数据库
"""
# 书籍表中所有书的名字
orm + for循环
# 想实现获取一个只有title字段的数据对象
res = models.Book.objects.only(‘title‘) # 拿到的是对象
for i in res:
i.title # 点only括号内的字段,不会走数据库
i.price # 点其余的字段,会重新走数据库查询;而all不需要
res = models.Book.objects.defer(‘title‘) # 拿到的数据对象
for i in res:
i.price # 点其余的字段,不走数据库
i.title # 点括号内的字段,走数据库
"""
defer括号内的字段不再查询出来的对象里面
only查询出来的对象里面只有括号内的字段
"""
select_related与prefetch_related:与跨表操作有关
res = models.Book.objects.all()
for i in res:
i.publish.name # 每循环一次,就要走一次数据库
res = models.Book.objects.select_related(‘publish‘) # INNER JOIN
"""
select_related会将book与publish连接起来,然后一次性将大表里面的所有数据全部封装给查询出来的对象
这个时候无论是点击book表里的数据还是publish的数据都无需走数据库查询了
select_related(只能放外键字段,一对一,一对多) 多对多关系不行
"""
models.Book.objects.prefetch_related(‘publish‘) # 子查询
"""
该方法内部原理就是子查询,然后将查询出来的结果封装给对象
"""
# 数据库设计的时候常用
"""
针对某个可以列举完全的可能性字段,我们应该如可存储
只要某个字段的可能性是可以列举完全的,那么一般情况下都会采用choices参数
"""
比如:
gender_choices = (
(1,‘男‘),
(2,‘女‘)
)
gender = models.IntegerField(choices=gender_choices)
"""
该字段存的还是数字,但是如果存的数字在gender_choices中,可以简单获取真正的内容
存的时候,没有列举出来的数字也能存
取的时候,
只要是choices的字段,如果想要获取对应信息,get_xxx_display(),固定写法
"""
# 这个参数使用场景非常多
# 全自动:利用ORM自动帮我们创建第三张表
models.ManyToManyField(to=‘‘)
"""
优点:代码不需要写,方便,还支持ORM提到操作第三张关系表的方法
不足之出:第三张关系表的扩展性极差(无法额外添加字段……)
"""
# 纯手动
自己创建第三张表,自己创建外键字段,自己关联相关表
"""
优点:自定义关系,扩展性好
不足之处:需要写的代码较多,不能够使用ORM提供的简单的方法
"""
# 半自动
# 还是需要手动创建表,外键字段
# 并且,还需要再基表中,添加
models.ManyToManyField(to=‘‘,through=‘第三张表‘,through_fields=(‘book‘,‘author‘))
"""
through_fields字段先后顺序
判断的本质:
通过第三张表查询对应的表,需要用到哪个字段,就把哪个字段放在前面
可以使用ORM的正反向查询,但是没法使用add,set,remove,clear这四个方法
"""
标签:函数 any 默认 帮助 级联 虚拟 sel nta lte
原文地址:https://www.cnblogs.com/qijiaxun/p/14257478.html