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。所有参数都是可选的,但你至少要使用一个
      简单示例:
# select
s = User.objects.extra(select={'is_recent':"both>'2000-01-01'"})
# 结果集中每个对象都有一个额外的属性is_recent, 它是一个布尔值,表示 User对象的both 是否晚于2000-01-01
# 可以和filter()、exclude() 等等连用

# where
s = User.objects.extra(where=['id in (0,10)','name like "王"','id<8'])
# where和tables都接受字符串列表。所有where参数均为“与”任何其他搜索条件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值