Dganjo ORM的F&Q
Dganjo ORM的F&Q
1.F
F的作用:用来批量修改数据用的
比如我有一个age这个列,我想让所有的age自+1或者某些人自+1
model.tb.object.all().update(age=F('age')+1)
这个F就代表当前行的age
导入F模块
from django.db.models import F
2.Q
Q的作用:Q是用来做条件查询的
有没有这么一种情况:username=sunqihu 或 username=jay或 username=wusir并且 age=18的需求?原生的查询是不支持的!所以就用到了Q~
from django.db.models import Q 导入模块 conn= Q() 生成一个搜索对象 conn.connector = 'OR' 标记conn中搜索条件为‘或’ 查询 q=Q() conn.add(q,'AND') 可以生成多个小Q,把多个搜索条件进行合并,添加类型
这个Django中的Q是非常常用的东西,并且非常有趣!
首先看下他的格式其实不是很难!
第一步: #生成一个搜索对象 search_q = Q() #在生成两个搜索对象 search1 = Q() search2 = Q() 第二步: #标记search1中的搜索条件为 ‘ 或’ 查询 search1.connector = 'OR' #把搜索条件加入到search1中 search1.children.append(('字段名','字段内容')) search1.children.append(('字段名','字段内容')) search1.children.append(('字段名','字段内容')) search1.children.append(('字段名','字段内容')) #标记search2中的搜索条件为 ‘ 或’ 查询 search2.connector = 'OR' #把搜索条件加入到search2中 search2.children.append(('字段名','字段内容')) search2.children.append(('字段名','字段内容')) search2.children.append(('字段名','字段内容')) search2.children.append(('字段名','字段内容')) 第三步: #把多个搜索条件进行合并 search_q.add(search1,'AND') search_q.add(search2,'AND') 第四步: #执行搜索 models.HostInfo.objects.filter(search_q)
小实例分享
实例1:
在前端获取搜索条件的时候我把相同类型的搜索写成字典的形式{字段名:[条件结合列表]},这样我在查询的时候直接通过循环字典就可以把搜索条件分为不同的子条件!
function SearchSubmit() { //清空当前列表 $('#table-body').children().remove(); //设置一个空字典 SEARCH_DIC = {}; //找到所有的搜索框体 var search_data = $('.inputs').find("input[is-condition='true']"); //循环找到的内容 $.each(search_data,function (index,data) { //获取搜索的类型 /* 这里需要注意:重点::::: 这里和Django的Q可以进行耦合,在我们定义搜索的类型的时候可以直接写成我们要搜索的的'库中的字段或者条件都可以!!!' 如下: <input is-condition="true" type="text" placeholder="逗号分割多条件" class="form-control no-radius" name="hostname" /> */ var search_name = $(this).attr('name'); //获取搜索的值 var search_value = $(this).val(); if(SEARCH_DIC.hasOwnProperty(search_name)){//判断是否有这个KEY SEARCH_DIC[search_name].push(search_value) }else{ SEARCH_DIC[search_name] = [search_value] } } );//ajax请求结束 $.get("{% url 'search_info' %}",{'search_list':JSON.stringify(SEARCH_DIC)},function(callback){ $('#table-body').append(callback) });//搜索按钮结束
这里需要注意:
重点:
在前端我们定义input的name属性的时候,我们可以直接定义为数据库中的“字段名”,并且在Django的Q中支持跨表操作“双下划线”,所以我们在定义name的时候可以直接定义双下划线操作
search1.children.append(('字段名'__'跨表字段名','跨表字段内容'))
@login_auth def search_info(request): #获取用户请求的数据 user_post = json.loads(request.GET['search_list']) print user_post #生成搜索对象 Serach_Q = Q() #循环字典并生成搜索条件集合 for k,v in user_post.items(): #生成一个搜索结合 q = Q() #生命集合中的搜索条件为'或'条件 q.connector = 'OR' #循环字典中的value,value是前端传过来的条件集合 for i in v: #在搜索条件集合中增加条件,条件为元组形式,k为字典中的key! key是字段名或者跨表字段名或者支持_gt等 #i为字典中的vlaue中的元素,为条件 # q.children.append((k,i)) #没循环一次后后,吧他加入到总的搜索条件中 Serach_Q.add(q,'AND') #使用总的搜索条件进行查询 data = models.HostInfo.objects.filter(Serach_Q) #拼接字符串并返回 html = [] for i in data: html.append( "<tr>"+ "<td>" + "<input type='checkbox' >"+ "</td>" + "<td name='host_id'>" + '%s' %i.id + "</td>" + "<td name='host_name' edit='true'>" + i.hostname + "</td>"+ "<td name='host_ip' edit='true'>" + i.hostip + "</td>"+ "<td name='host_port' edit='true'>" + '%s' %i.hostport + "</td>"+ "<td name='host_business' edit='true' edit-type='select' global-key='BUSINESS' select-val='" + '%s' %i.hostbusiness_id + "'>" + i.hostbusiness.hostbusiness + "</td>"+ "<td name='host_status' edit='true' edit-type='select' global-key='STATUS' select-val='" + '%s' %i.hoststatus_id + "'>" + i.hoststatus.hoststatus + "</td>"+ "</tr>" ) html = mark_safe("".join(html)) return HttpResponse(html)
结果
实例2
目录
urls.py
from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^test/', views.test), ]
views.py
from django.shortcuts import render,HttpResponse from app1 import models # Create your views here. import json def test(request):
# models.BookType.objects.create(caption='技术') # models.BookType.objects.create(caption='文学') # models.BookType.objects.create(caption='动漫') # models.BookType.objects.create(caption='男人装') # models.Book.objects.create(name='文艺复兴',pages='100',price='40',pubdate='1992-11-2',book_type_id='1') # models.Book.objects.create(name='解密',pages='80',price='10', pubdate='2016-6-10',book_type_id='2') # models.Book.objects.create(name='刀锋',pages='50',price='3', pubdate='2014-02-16',book_type_id='2') # models.Book.objects.create(name='查令十字路84号',pages='260',price='40',pubdate='1999-10-12',book_type_id='3') # models.Book.objects.create(name='红楼',pages='1000',price='500', pubdate='1760-1-1',book_type_id='3') # models.Book.objects.create(name='将夜',pages='2000',price='300', pubdate='2010-3-3',book_type_id='1') # models.Book.objects.create(name='mysql从删库到跑路',pages='20',price='10',pubdate='1998-9-2',book_type_id='4') # models.Book.objects.create(name='马克思主义',pages='50',price='100',pubdate='1937-3-3',book_type_id='2')
return HttpResponse('ok') import json from datetime import date from datetime import datetime from decimal import Decimal class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime): return field.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return field.strftime('%Y-%m-%d') elif isinstance(field, Decimal): return str(field) else: return json.JSONEncoder.default(self, field) def index(request): if request.method == 'POST': ret = {'status': False, 'message': '', 'data':None} try: post_data = request.POST.get('post_data',None) # post_data用户输出得到的内容 post_data_dict = json.loads(post_data) #//转成python的数据类型 print(post_data_dict) # {'name': ['11', 'sdf'],'price': ['11', 'sdf']} # 构造搜索条件 # Q的作用:Q是用来做条件查询的。 from django.db.models import Q con = Q() ###生成一个搜索对象 for k,v in post_data_dict.items(): #循环得到的数据 q = Q() ##生成一个搜索对象 q.connector = 'OR' ##标记search1中的搜索条件为 ‘ 或’ 查询 print(v,'---------------vvvvvvvvvvvvvvvvvvvvvv') print(k,'---------------kkkkkkkkkkkkkkkkkkkk>>>>>>>>>>>>>>>>') # ['红楼'] - --------------vvvvvvvvvvvvvvvvvvvvvv # name - --------------kkkkkkkkkkkkkkkkkkkk >> >> >> >> >> >> >> >> for item in v: ##v是搜索的结果集,可能是多个 print(item,'item--------------------->>>>>>>>>>>>红楼') # 把搜索条件加入到q中 (字段名,字段内容) q.children.append((k, item)) ##k就是name item就是值 con.add(q, 'AND') # 把多个搜索条件进行合并 """ ret = models.Book.objects.filter(con) print(ret) # queryset,[对象] from django.core import serializers data = serializers.serialize("json", ret) print(type(data),data) # 字符串 """ """ #ret = models.Book.objects.filter(con).values('name','book_type__caption') ret = models.Book.objects.filter(con).values_list('name', 'book_type__caption') print(ret,type(ret)) li = list(ret) data = json.dumps(li) print(data,type(data)) """ # #执行搜索 result = models.Book.objects.filter(con).values('name','price','pubdate','book_type__caption') # ret = models.Book.objects.filter(con).values_list('name', 'book_type__caption') li = list(result) ret['status'] = True ret['data'] = li except Exception as e: ##查找不到 ret['message'] = str(e) #分装错误信息 ret_str = json.dumps(ret, cls=JsonCustomEncoder) return HttpResponse(ret_str) # return render(request, 'index.html')
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .left{ float: left; } .clearfix:after{ content: '.'; clear: both; display: block; visibility: hidden; height: 0; } </style> </head> <body> <div class="condition"> <div class="item clearfix"> <div class="icon left" onclick="AddCondition(this);">+</div> <div class="left"> <select onchange="ChangeName(this);"> <option value="name">书名</option> <option value="book_type__caption">图书类型</option> <option value="price">价格</option> <option value="pages">页数</option> </select> </div> <div class="left"><input type="text" name="name" /></div> </div> </div> <div> <input type="button" onclick="Search();" value="搜索" /> </div> <div class="container"> </div> <script src="/static/jquery-1.12.4.js"></script> <script> function AddCondition(ths) { var new_tag = $(ths).parent().clone(); //找到他的父级标签进行克隆 new_tag.find('.icon').text('-'); new_tag.find('.icon').attr('onclick', 'RemoveCondition(this);'); //添加事件 $(ths).parent().parent().append(new_tag); //追加到父级父级进行追加 } function RemoveCondition(ths) { $(ths).parent().remove(); //自定义属性,找到他的父级进行删除 } function ChangeName(ths) { var v = $(ths).val(); //获取类型 $(ths).parent().next().find('input').attr('name',v); //设置他的name就是类型 } function Search() { //提交数据 var post_data_dict = {}; // 获取所有input的内容,提交数据 $('.condition input').each(function () { // console.log($(this)[0]) var n = $(this).attr('name');//获取属性 var v = $(this).val(); //input得到的值 var v_list = v.split(','); //得到的值进行分割 post_data_dict[n] = v_list; //获取到 }); console.log(post_data_dict); var post_data_str = JSON.stringify(post_data_dict); {# stringify()用于从一个对象解析出字符串#} $.ajax({ url: '/index/', type: 'POST', data: { 'post_data': post_data_str}, dataType: 'json', success: function (arg) { // 字符串 "<table>" + if(arg.status){ //数据库可以查到的话 var table = document.createElement('table'); //创建table表格 table.setAttribute('border',1); //设置属性 // [{,name,pubdate,price,caption},] $.each(arg.data, function(k,v){ //\循环返回的数据 var tr = document.createElement('tr'); var td1 = document.createElement('td'); td1.innerText = v['name']; //名字 var td2 = document.createElement('td'); td2.innerText = v['price']; //价格 var td3 = document.createElement('td'); td3.innerText = v['book_type__caption']; //类型 var td4 = document.createElement('td'); td4.innerText = v['pubdate']; //发布时间 tr.appendChild(td1); //追加到后面 tr.appendChild(td2); tr.appendChild(td3); tr.appendChild(td4); table.appendChild(tr); //然后把(BOSS)tr放入table }); $('.container').empty(); // $('.container').append(table); }else{ alert(arg.message); //找不到返回错误信息 } } }) } </script> </body> </html>
models.py
from django.db import models class BookType(models.Model): ''' 图书类型 ''' caption = models.CharField(max_length=64) class Book(models.Model): ''' 图书 ''' name = models.CharField(max_length=64) pages = models.IntegerField() price = models.DecimalField(max_digits=10, decimal_places=2) # 数字长度max_digits,有效位数decimal_places pubdate = models.DateField() ##出版时间 # authors = models.ManyToManyField(Author) book_type = models.ForeignKey(BookType) # 注意:Django 1.7.1及以上的版本需要用以下命令 # python manage.py makemigrations # python manage.py migrate
效果