Django - ORM使用记录(二)

ORM查询
  • queryset和objects对象
    • 1.queryset是查询集,就是传到服务器上的url里面的内容。Django会对查询返回的结果集QerySet进行缓存,这里是为了提高查询效率,也就是说,在你创建一个QuerySet对象的时候,Django并不会立即向数据库发出查询命令,只有在你需要用到这个QuerySet的时候才回去数据库查询
    • 2.Objects是django实现的mvc框架中的数据层(model)m,django中的模型类都有一个objects对象,它是一个django中定义的QuerySet类型的对象它包含了模型对象的实例。简单的说,objects是单个对象,queryset是许多对象
    • 3.QuerySet 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作。只要你查询的时候才真正的操作数据库
管理器方法 返回类型 说明
模型类.objects.all() QuerySet 返回表中所有数据
filter() QuerySet 返回符合条件的数据
values() ValuesQuerySet(QuerySet的子类) 返回一个列表 每个元素为一个字典
values_list() ValuesListQuerySet(QuerySet的子类) 返回一个列表,不过它的元素不是字典,而是元组
get() 模型对象 返回一个满足条件的对象; 如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常; 如果找到多个,会引发模型类.MultiObjectsReturned 异常
first() 模型对象 返回第一条数据
last() 模型对象 返回最后一条数据
exclude() QuerySet 返回不符合条件的数据
order_by() QuerySet 对查询结果集进行排序
reverse() QuerySet 对排序的结果反转
count() int 返回查询集中对象的数目
exists() bool 判断查询的数据是否存在
  • 1.len()与count()

    • 计算QuerySet元素的数量,并不推荐使用len(),除非QuerySet是求过值的(即evaluated),否则,用QuerySet.count()获取元素数量,这个效率要高很多,特别在数据量大(上万)的时候
  • 2.if QuerySet: 与 if QuerySet.exists()

    • 同样不建议if QuerySet这种方法判断是否为空,而应该使用QuerySet.exists(),查询效率高
  • 3.F类

from django.db import models
from django.db.models import F

class User(models.Model):
    name = models.CharField(max_length=10)
    age = models.IntegerField()
    both = models.CharField(max_length=20)

不使用F()

s = User.objects.get(name='xxx')
s.age += 1
s.save()

将对象从数据库中查出来放到内存中,然后计数,再存入到数据库中

使用F()

s = User.objects.get(name='xxx')
s.age = F('age') + 1
s.save()

直接在数据库中查出数据,计数后更改数据库

    1. Q类 - 对应(and/or/not)
    • 如果有or等逻辑关系呢,那就用Q类
    • filter中的条件可以是Q对象与非Q查询混和使用,但不建议这样做,因为混和查询时Q对象要放前面,这样就有难免忘记顺序而出错,所以如果使用Q对象,那就全部用Q对象
    • Q对象也很简单,就是把原来filter中的各个条件分别放在一个Q()即可,不过我们还可以使用或与非,分别对应符号为”|”和”&”和”~”,而且这些逻辑操作返回的还是一个Q对象,另外,逗号是各组条件的基本连接符,也是与的关系,其实可以用&代替(在python manage.py shell测试过,&代替逗号,执行的SQL是一样的),不过那样的话可读性会很差,这与我们直接写SQL时,各组条件and时用换行一样,逻辑清晰
>>> python manage.py shell
>>> from django.db.models import Q
>>> Poll.objects.get( Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')   # 正确,但不要这样混用
>>> Poll.objects.get( Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
Q(question__startswith='Who'))  # 推荐,全部是Q对象
>>> Poll.objects.get( (Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))&
Q(question__startswith='Who'))  # 与上面语句同意,&代替”,”,可读性差

Q类中时应该可以使用F类吗?? 有兴趣的可以试一下

  • annotate(无对应SQL关键字)
    • 函数annotate(*args, **kwargs):返回QuerySet
    • 往每个QuerySet的model instance中加入一个或多个字段,字段值只能是聚合函数,因为使用annotate时,会用group by,所以只能用聚合函数。聚合函数可以像filter那样关联表,即在聚合函数中,Django对OneToOne、OneToMany、ManyToMany关联查询及其反向关联提供了相同的方式

示例:

from django.db.models import Count
s = User.objects.all().annotate(n=Count('age'))
  • 5.order_by()

    • 如果直接用字段名,那就是升序asc排列;如果字段名前加-,就是降序desc
    • 返回QuerySet
  • 6.distinct()

    • 一般与values()、values_list()连用,这时它返回ValuesQuerySet、ValuesListQuerySet这个类跟列表很相似,它的每个元素是一个字典
    • 它没有参数(其实是有参数的,不过,参数只在PostgreSQL上起作用)
      示例:
s = User.objects.values('name').distinct()
  • 7.aggregate
    • aggregate(*args,**kwargs):参数为聚合函数,最好用**kwargs的形式,每个参数起一个名字
    • annotate相当于aggregate()和group_by的结合,对每个group执行aggregate()函数。而单独的aggregate()并没有group_by
from django.db.models import Count
# 这是用*args的形式,最好不要这样用
s = User.objects.aggregate(Count('name'))
# 这是用**kwargs的形式
s = User.objects.aggregate(n=Count('name'))
  • 8.模糊查询

    • gt/gte/lt/lte对应>,>=,<,<=:字段名加双下划线
      • age__gt=18:年龄大于18
    • in对应in:字段名加双下划线
    • contains/startswith/endswith对应like:字段名加双下划线
    • range对应between and:字段名加双下划线,range后面值是列表
    1. extra()
    • extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    • 实现复杂的where字句,在 extra 可以指定一个或多个 params 参数,如 select,where 或 tables。所有参数都是可选的,但你至少要使用一个
      简单示例:
s = User.objects.extra(select={'is_recent':"both>'2000-01-01'"})s

转载于:https://www.jianshu.com/p/80a6e504c11a

猜你喜欢

转载自blog.csdn.net/weixin_33851429/article/details/91182298