美文网首页
Django - ORM使用记录(二)

Django - ORM使用记录(二)

作者: 憧憬001 | 来源:发表于2019-06-05 20:57 被阅读0次
    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
    

    相关文章

      网友评论

          本文标题:Django - ORM使用记录(二)

          本文链接:https://www.haomeiwen.com/subject/smxexctx.html