django model练习2 基于model的Q和ajax 实现搜索多条件的案例
1 项目准备参考我的另一篇博客
http://www.cnblogs.com/liujianzuo888/articles/5798658.html
Django model 练习
本案例小点总结:
前端 + 下拉框(书名) <input name='name' /> python之路,python红宝书 - 下拉框(图书类型)<input name='book_type__caption' /> 文学 - 下拉框(价格)<input name='price' /> 59,77 搜索框 $.each() dict = { "name": [python之路,python红宝书], "book_type__caption": [文学,], "price": [11,2] } ==>列表序列化 $.ajax({ data: dict success: function(arg){ 数据,生成HTML标签, document.createElement(...) 添加指定位置 } }) 后端 request.POST.get('name') request.POST.get('book_type__caption') request.POST.get('price') con = Q() q1 = Q() [python之路,python红宝书 或者 q2 = Q() [文学,], 或者 ,,, con.(q1,q2,q3) result = model.Book.objects.filter(con).values() return HttpResponse(result序列化)
2 model类的建表
class Author(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() 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) pubdate = models.DateField() authors = models.ManyToManyField(Author) book_type = models.ForeignKey(BookType)
生成测试数据
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='1') models.Book.objects.create(name='刀锋',pages='50',price='3', pubdate='2014-02-16',book_type_id='1') 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='2') models.Book.objects.create(name='mysql从删库到跑路',pages='20',price='10',pubdate='1998-9-2',book_type_id='2') models.Book.objects.create(name='马克思主义',pages='50',price='100',pubdate='1937-3-3',book_type_id='2')
3 页面搜索框
indexhtml
<!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); } function Search() { var post_data_dict = {}; // 获取所有input的内容,提交数据 $('.condition input').each(function () { // console.log($(this)[0]) var n = $(this).attr('name'); var v = $(this).val(); 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); $.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.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); }); $('.container').empty(); $('.container').append(table); }else{ alert(arg.message); } } }) } </script> </body> </html>
分开解释 用到的知识点
1 js
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(); }
2 子div都飘撑起父亲div
.clearfix:after{ content: '.'; clear: both; display: block; visibility: hidden; height: 0; }
3 搜索:条件切片 发送ajax
function Search() { var post_data_dict = {}; // 获取所有input的内容,提交数据 $('.condition input').each(function () { // console.log($(this)[0]) var n = $(this).attr('name'); var v = $(this).val(); 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); $.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.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); }); $('.container').empty(); $('.container').append(table); }else{ alert(arg.message); } } }) }
4 ajax 提交的url一定要加/
发送ajax提交时候的url的路径一定要加/
$.ajax({ url: '/index/', type: 'POST', })
4 后端的 view文件
from django.shortcuts import render,HttpResponse from app01 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): # 序列化时候json处理不了的我们需要自己做转换为json可以转换的数据类型 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_dict = json.loads(post_data) print(post_data_dict) # {'name': ['11', 'sdf'],'price': ['11', 'sdf']} # 构造搜索条件 from django.db.models import Q con = Q() for k,v in post_data_dict.items(): q = Q() q.connector = 'OR' for item in v: q.children.append((k, item)) con.add(q, 'AND') # django两种 序列化数据返回前端的方法 #1 serialize 但是如果是数据的外键字段不会自动查询只会放回字典表id """ ret = models.Book.objects.filter(con) print(ret) # queryset,[对象] from django.core import serializers data = serializers.serialize("json", ret) print(type(data),data) # 字符串 """ # 通过json方式,这种事数据类型没有特殊的,json只能列表 字典 字符串 """ #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) # 如果想让json也能处理decimal date类型的数据就需要自己写一个类处理 cls接收 会一个个循环ret的去处理。 ret_str = json.dumps(ret, cls=JsonCustomEncoder) # return HttpResponse(ret_str) return render(request, 'index.html') def test(request): # 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='1') # models.Book.objects.create(name='刀锋',pages='50',price='3', pubdate='2014-02-16',book_type_id='1') # 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='2') # models.Book.objects.create(name='mysql从删库到跑路',pages='20',price='10',pubdate='1998-9-2',book_type_id='2') # models.Book.objects.create(name='马克思主义',pages='50',price='100',pubdate='1937-3-3',book_type_id='2') return render(request,"test.html")
解释用到的知识点
1 返回ajax 的序列化问题
2 model 的Q应用
# {'name': ['11', 'sdf'],'price': ['11', 'sdf']} # 构造搜索条件 from django.db.models import Q con = Q() for k,v in post_data_dict.items(): q = Q() q.connector = 'OR' for item in v: q.children.append((k, item)) con.add(q, 'AND') result = models.Book.objects.filter(con).values('name','price','pubdate','book_type__caption') li = list(result)
5 前端ajax success收到数据后的处理注意点
标签操作
a. 创建标签
// 方式一 创建的方式 var tag = document.createElement('a') tag.innerText = "wupeiqi" tag.className = "c1" tag.href = "http://www.cnblogs.com/wupeiqi" // 方式二 字符串拼接 var tag = "<a class='c1' href='http://www.cnblogs.com/wupeiqi'>wupeiqi</a>"
b.操作标签
// 方式一 insertAdjacentHTML var obj = "<input type='text' />"; xxx.insertAdjacentHTML("beforeEnd",obj); xxx.insertAdjacentElement('afterBegin',document.createElement('p')) //注意:第一个参数只能是'beforeBegin'、 'afterBegin'、 'beforeEnd'、 'afterEnd' // 方式二 标签添加子标签 创建<p>添加<a> var tag = document.createElement('a') xxx.appendChild(tag) // 为xxx标签添加子标签 xxx.insertBefore(tag,xxx[1])
success: function (arg) { // 字符串 "<table>" + if(arg.status){ var table = document.createElement('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); }); $('.container').empty(); $('.container').append(table); }else{ alert(arg.message); } }