本节涉及:

1.Q搜索在前后端的设计

2.Django中Queryset对象的序列化(由后端扔给前端的数据必然会经过序列化)

3.前端动态地构造表格以便显示(动态创建DOM对象)

思路:

用户通过前端查询数据库内容时,可添加多个搜索框,一个搜索框内可以输入多个条件。同一搜索框内的条件是或OR关系,不同搜索框间是与AND关系。如搜索图书,每条图书信息包括名称、页数、印刷日期、类型,在一个搜索框内可选择搜索书名,以中文逗号分隔即可以书名同时搜索多本图书,同一搜索框内就是OR关系。又可以再添加输入框,这时就可以再添加类型、价格等信息,缩小搜索范围,这些搜索框之间就是AND关系。条件传递给后端后,后端拿到结果,处理后再抛给前端,由前端在页面展示。

代码

数据库信息

class BookType(models.Model):
caption = models.CharField(max_length=32) class Book(models.Model):
name = models.CharField(max_length=32)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
pubdate = models.DateField()
# 外键
book_type = models.ForeignKey(BookType, on_delete=models.CASCADE) def __str__(self):
return "Book Object: %s %sp %s元" % (self.name, self.pages, self.price)

数据库信息

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="/static/js/jquery-2.1.4.min.js"></script>
<title>Index页面</title>
</head>
<body>
<!--搜索框-->
<div class="condition">
<div class="item ">
<!--点击后会添加一个搜索框-->
<div class='icon' onclick="AddCondition(this);">+</div>
<div>
<!--选择不同的搜索条件时,会触发方法-->
<select onchange="ChangeName(this);">
<option value="name">书名</option>
<option value="book_type__caption">类型</option>
<option value="price">价格</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>
</body>

index.html

JS代码

<script>
function AddCondition(ths){
// dom对象转换为jquery对象
var new_tag = $(ths).parent().clone();
// 新添加的搜索框的按钮改为减号,定义删除方法
new_tag.find('.icon').text('-');
new_tag.find('.icon').attr('onclick','RemoveCondition(this);');
$(ths).parent().append(new_tag);
} // 新添加的搜索框还可删除
function RemoveCondition(ths){
$(ths).parent().remove();
} //
function ChangeName(tag){
// 获取搜索条件value属性的值
var v = $(tag).val();
// 定义input的name属性
// 这里主要是为了随着用户选择不同的搜索条件
// 也向后端传递不同的搜索条件,Q搜索中会用到
$(tag).parent().next().find('input').attr('name', v);
} function Search(){
// 获取所有用户输入的内容并提交
// 将要给后端传递的字典
var post_data_dict = {};
// 循环所有的input
$('.condition input').each(
function(){
// 操作jquery对象
// 获得搜索条件
var attr_name = $(this).attr('name');
// 获取用户输入
var value_list = $(this).val().split(',');
post_data_dict[attr_name] = value_list;
}
);
// 将要传递的字典序列化
var post_data_str = JSON.stringify(post_data_dict);
$.ajax({
url: '/index/',
type: 'POST',
data: {'post_data': post_data_str},
// 此参数使得后端传来的json会被解析为js对象
dataType: "json",
success: function(ret){
if(ret.status){
// 清空展示柜,避免重复显示
$('.container').empty();
// {'status':true, 'content': [{},{}]}
$.each(ret.content, function(useless_key, value_dict){
// 有多少条数据就有多少个表
// 形式为一表一行n列
var table = document.createElement('table');
// 每个表有一行数据
var tr = document.createElement('tr');
// {'name':'xx', 'pages':540}
$.each(value_dict, function(key, val){
// 书籍信息的每一项内容对应一列 td
var td = document.createElement('td');
// 为td标签加上class属性,值为其键
td.setAttribute('class', key);
// 为td标签加上文本, 即其值
td.innerText = val;
td.setAttribute('width', 100);
// 每次创建一个td标签都添加到tr上
tr.appendChild(td);
});
// 将tr标签加入table中
table.appendChild(tr);
table.setAttribute('border', 1);
// 将table加入展示柜中
$('.container').append(table);
});
}else{
alert(ret.message);
}
}
})
}
</script>
</html>

JS代码

后端代码(views.py)

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
# Create your views here.
# 业务处理逻辑
import json
from decimal import Decimal
from datetime import date class DecimalDatetimeEncoder(json.JSONEncoder): def default(self, o):
if isinstance(o, Decimal):
return str(o)
elif isinstance(o, date):
return o.strftime('%Y-%m-%d')
return json.JSONEncoder.default(self, o) def index(request):
# 定义要给前端传递的字典
post_ret_dict = {'status': True, 'content': None}
if request.method == 'POST':
try:
# 获取前端抛来的字符串
post_data_str = request.POST.get('post_data', None)
# 反序列化
post_data_dict = json.loads(post_data_str)
# post_data_dict: {'name': ['nameA', 'nameB'],'price':[20,30,40] }
from django.db.models import Q
# 构造Q搜索
condition = Q()
for k, v in post_data_dict.items():
# 同一搜索框内(同一条件)的输入是OR关系(主关系)
q = Q()
q.connector = 'OR'
for item in v:
# 这里的k就是前端传来的name属性的值,也就是搜索条件(子关系)
q.children.append((k, item))
condition.add(q, 'AND')
# 将Q搜索直接作为filter的条件传入,并再用values方法取到想要的值
# 这里用book_type__caption双下划线的形式找到外键表的caption域的值
# 返回值仍是Queryset对象,可通过list转换为列表
list_ret = list(models.Book.objects.filter(condition).values('name', 'pages', 'price', 'pubdate', 'book_type__caption')) # QuerySet
post_ret_dict['content'] = list_ret
except Exception as e:
post_ret_dict['status'] = False
# 最后再序列化要给前端的内容
# 注意价格是Decimal类型,印刷日期是Datetime类型,这两类都不是python内置类型,无法直接用json.dumps方法序列化
# 这里可以借助第二个参数,构造一个自定义的解析类,自行处理
post_ret_str = json.dumps(post_ret_dict, cls=DecimalDatetimeEncoder)
return HttpResponse(post_ret_str) # django提供的序列化方法,但是无法获得外键表的对应值,不能在使用values方法后序列化
# from django.core.serializers import serialize
# ret = models.Book.objects.filter(condition) # QuerySet
# str_ret = serialize('json', ret)
# print(str_ret)
# return HttpResponse(str_ret)
return render(request, "index.html")

views.py

Django中Q搜索的简单应用的更多相关文章

  1. Django中Q查询及Q()对象

    问题 一般我们在Django程序中查询数据库操作都是在QuerySet里进行进行,例如下面代码: >>> q1 = Entry.objects.filter(headline__st ...

  2. Django中组合搜索功能

    需求分析 很多电商网站中有组合搜索的功能,所谓组合搜索就是网页中组合多个条件,对数据库中进行查询,并且将结果显示在页面中,看个例子吧: 注意红框中的标识,我们可以根据URL来做组合搜索. video- ...

  3. Asp.net 中高亮显示搜索关键字简单方法

    今天用到搜索时的高亮显示,百度了一下,如下面: 1.替换关键字,对字体变色.         public static string ReplaceRed(string strtitle, stri ...

  4. Django 中的缓存问题

    Django 中的缓存问题 简单介绍 ​ 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. ​ 当一个网站的用户访问量很大的 ...

  5. 【Django】Django中的模糊查询以及Q对象的简单使用

    Django中的模糊查询: 需要做一个查找的功能,所以需要使用到模糊查询. 使用方法是:字段名加上双下划线跟上contains或者icontains,icontains和contains表示是否区分大 ...

  6. Django中的F和Q函数

    内容简介: 介绍Django中的F和Q作用以及使用方法 一.F介绍 作用:操作数据表中的某列值,F()允许Django在未实际链接数据的情况下具有对数据库字段的值的引用,不用获取对象放在内存中再对字段 ...

  7. Django中的ORM相关操作:F查询,Q查询,事物,ORM执行原生SQL

    一    F查询与Q查询: 1 . F查询: 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢? Django 提供 F() 来做这样的 ...

  8. Django中简单添加HTML、css、js等文件(非正规添加,适合小白)

    Django中简单添加HTML.css.js等文件 首先申明下自己的环境, python版本3.65(亲测3.7版本有毒,没解决掉!) Django版本1.11.15(版本比较成熟,也可以用最新的版本 ...

  9. django 中的聚合和分组 F查询 Q查询 事务cookies和sessions 066

    1 聚合和分组 聚合:对一些数据进行整理分析 进而得到结果(mysql中的聚合函数) 1aggregate(*args,**kwargs) : 通过对QuerySet进行计算 ,返回一个聚合值的字典. ...

随机推荐

  1. 金融量化分析【day113】:多因子选股

    一.什么是多因子选股 在股市中征战过的朋友们应该知道,股市之道无非三点.1择时,2选股,3 仓控.精通这三点中的任何一点,都足以在股市中所向披靡.但是精通二字何其艰难!!!矫情的话多不多说,咱们进入正 ...

  2. matlab运行出现“变量似乎会随着迭代次数改变而变化,请预分配内存,以提高运行速度”问题

    这句话大致意思就是: b = 0;for i = 1:3    a(i) = b;end是说变量的长度是变化的,经常在循环里出现,比如上面这个例子,这样会影响计算速度,最好的办法是预先定义a的长度,比 ...

  3. Cygwin添加到鼠标右键

    From:http://www.cnblogs.com/killerlegend/p/3960112.html 在cygwin中安装chere 管理员权限执行mintty,输入下列命令即可. cher ...

  4. PyQt5之窗口类型

    [TOC] 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 写在开头 1.1 本文内容 本文的主要内容:PyQt中的窗口部件:QMainWindow,QWidget,QDialog. 上述三 ...

  5. 第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)

    一. 语法糖简介   语法糖也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方 ...

  6. python的os.system函数的应用

    os的system原理 system函数可以将字符串转化成命令在服务器上运行:其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程 上述原理会导致 ...

  7. JavaScript的数据类型和变量

    1.  数据类型:JS使用弱类型,共4种基本类型,其数据可以是变量,也可以是常量. a)         数值(整数和实数) b)         字符串型(用“”号或‘’括起来的字符或数值) c)  ...

  8. Entity Framework查询

    Entity Framework是个好东西,虽然没有Hibernate功能强大,但使用更简便.今天整理一下常见SQL如何用EF来表达,Func形式和Linq形式都会列出来(本人更喜欢Func形式). ...

  9. django drf 基础学习4

    0  简介:介绍ModelViewSet基本使用规则1 views引用以及初始化   from rest_framework.viewsets import ModelViewSet     clas ...

  10. python常用校验方法总结

    0x00 校验一个字符串是否是合法IP地址 ipv4举例:利用正则表达式来匹配 def checkip(ip): p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d ...