Django运算表达式与Q对象/F对象

1 模型查询

概述:
1 查询集:表示从数据库中获取的对象的集合
2 查询集可以有多个过滤器,通过 逻辑运算符连接
3 过滤器就是一个函数,基于所给的参数限制查询的结果,类似MySQL模糊查询中where语句
4 查询集等同select语句

2 查询集

特点:
1 查询集通过调用过滤器方进行查询, 查询集经过过滤器筛选后返回新的查询集,可以链式调用
2 惰性执行  创建查询集不会带来任何数据库的访问直到调用数据库才会访问

返回单个数据查询:
get()  	  返回一个满足条件的对象
		 注意:没有找到符合条件的对象,模型类引发异常  模型类.DoesNotExists异常
		 如果找到多个对象也会引发异常   模型类.MultipleObjectsReturned
count()   返回查询集中的对象个数
first()   返回第一个查询集对象
last()    返回最后一个查询集对象
exists()  查询集是否有数据,如果有数据返回true

限制查询集:查询集返回的是列表,可以采用下标的方法进行限制,等同于sql中的limit语句
studentList = Student.objects.all()[0:5]

查询集缓存 : 每个查询集都包含一个缓存,来最小化的对数据库访问。在新建的查询集中,缓存首次为空,第一次对查询				集求值,django会将数据缓存,并返回结果,以后结果直接使用缓存集的数据

3 常见过滤器

all()   	返回所有对象
filter()     filter(键=值,键=值)  且关系
			返回符合条件的数据
			filter(键=值),filter(键=值)
exclude()   过滤掉符合条件数据
order_by()  排序
values()    一条数据就是是一个对象(字典),返回一个列表

4 比较运算符

(1)概述: 实现where语句,作为filter()  exclude()  get()的参数
   语法: 属性名称__运算符 = 值
   外键: 属性名_id
   转义: 类似like语句,是为了匹配占位,匹配数据中的%,sql中where like '\%'
         filter(sname__contains = '%')
	  
(2)常见的比较运算符:
    exact 	     判断,大小写敏感
                 filter(isDelete=False)
    contains     是否包含,大小写敏感
                stuList = Student.objects.filter(sname__contains ='孙' )
    startswith   以value开头,大小写敏感
                stuList = Student.objects.filter(sname__startswith ='孙' )
    endwith      以value结尾,大小写敏感	
 	in   是否包含在范围内    filter(pk__in=[2,4,6,8,10])
 注: 以上四个前面加上i,就表示不区分大小写,iexact,icontains,istartswith,iendswith
    
(3) 其他形式查询
为空判断:
    isnull ,isnotnull   是否为空   filter(sname__isnull=Flase)  
比较运算:
    gt   大于
    gte  大于等于
    lt   小于
    lte  小于等于
    filter(sage_gt=30)年龄大于30
时间查询:
    year/month/day/week_day/hour/minute/second   filter(lastTime__year=2017)
    跨关查询   处理join查询   模型类型__属性名__运算符(可选)
    查询快捷   pk   代表的主键	

5 F对象与Q对象

常见的聚合函数:
使用aggregate()函数返回聚合函数的值
Avg  Count   Max   Min   sum

from dango.db.models import Max
maxAge = Student.objects.aggregate(Max('sage'))   找出学生年龄最大的

F对象
1 可以使用模型的A属性与B属性进行比较
    from django.db.models  import F,Q
    def grades(request):
	g = Grades.objects.filter(ggirlnum_gt=F('gboynum'))   找到女生人输大于男生人数的班级
2 支持F对象的算术运算  filter(ggirlnum_gt=F('gboynum')+20)
3 F对象的参数可以是跨表字段
	models.Book.objects.filter(bread_num=F(''author_name'))
4 F对象参数如果是date/time,可以进行日期的加减运算:
	models.Book.objects.filter(bpub_date__lt=F('bpub_date') + timedelta(days=5))
	
Q对象
概述    过滤器的方法中的关键字参数,,条件为And模式,采用逻辑或引入Q对象
需求    进行or查询,或查询
解决    使用Q对象

Q对象可以使用&(and)、|(or)操作符组合起来
studentList = Student.objects.filter(Q(pk__lt = 3)|Q(sage__gt=50))  pk_id小于3或年龄大于50岁
models.User.objects.filter(Q(username='老王') & Q(userpass='admin'))   条件与组合
models.User.objects.filter(~Q(username='老王'))   条件非表示取反
可以使用 &(and) |(or)  ~(not) 结合括号进行分组,构造更复杂的Q对象
filter函数可以传递一个或多个Q对象作为位置参数,如果有多个Q对象,这些参数的逻辑为and

下面分享一个综合用法:

 def get(self, request, *args, **kwargs):
        filters = request.GET
        #找出符合customer的数据转成列表
        Qs = [Q(customer=request.user.customer)]
        try:
            if 'limit' in filters:
                limit = abs(int(filters['limit']))
                if limit > 50:
                    limit = 50
            else:
                limit = 15
            start_id = int(filters.get('start_id', 0))
            #添加符合start_id的对象
            Qs.append(Q(id__gt=start_id))
            #添加符合状态的state
            if 'state' in filters:
                Qs.append(Q(state__in=filters['state']))
            else:
                Qs.append(Q(state__in=[0, 1, 2, 3, 4]))
            #添加符合title的数据
            if 'title' in filters:
                Qs.append(Q(title__contains=filters['title']))
        except Exception:
            return params_error({"filters": "过滤参数不合法"})
        
        #通过*Qs,对列表数据同时满足上述情况的数据进行总的帅选,并设置限制集
        sets = Questionnaire.objects.filter(*Qs)[:limit]