Django中Q搜索的简单应用
本节涉及:
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搜索的简单应用的更多相关文章
- Django中Q查询及Q()对象
问题 一般我们在Django程序中查询数据库操作都是在QuerySet里进行进行,例如下面代码: >>> q1 = Entry.objects.filter(headline__st ...
- Django中组合搜索功能
需求分析 很多电商网站中有组合搜索的功能,所谓组合搜索就是网页中组合多个条件,对数据库中进行查询,并且将结果显示在页面中,看个例子吧: 注意红框中的标识,我们可以根据URL来做组合搜索. video- ...
- Asp.net 中高亮显示搜索关键字简单方法
今天用到搜索时的高亮显示,百度了一下,如下面: 1.替换关键字,对字体变色. public static string ReplaceRed(string strtitle, stri ...
- Django 中的缓存问题
Django 中的缓存问题 简单介绍 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的 ...
- 【Django】Django中的模糊查询以及Q对象的简单使用
Django中的模糊查询: 需要做一个查找的功能,所以需要使用到模糊查询. 使用方法是:字段名加上双下划线跟上contains或者icontains,icontains和contains表示是否区分大 ...
- Django中的F和Q函数
内容简介: 介绍Django中的F和Q作用以及使用方法 一.F介绍 作用:操作数据表中的某列值,F()允许Django在未实际链接数据的情况下具有对数据库字段的值的引用,不用获取对象放在内存中再对字段 ...
- Django中的ORM相关操作:F查询,Q查询,事物,ORM执行原生SQL
一 F查询与Q查询: 1 . F查询: 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢? Django 提供 F() 来做这样的 ...
- Django中简单添加HTML、css、js等文件(非正规添加,适合小白)
Django中简单添加HTML.css.js等文件 首先申明下自己的环境, python版本3.65(亲测3.7版本有毒,没解决掉!) Django版本1.11.15(版本比较成熟,也可以用最新的版本 ...
- django 中的聚合和分组 F查询 Q查询 事务cookies和sessions 066
1 聚合和分组 聚合:对一些数据进行整理分析 进而得到结果(mysql中的聚合函数) 1aggregate(*args,**kwargs) : 通过对QuerySet进行计算 ,返回一个聚合值的字典. ...
随机推荐
- Docker:Docker 性质及版本选择 [三]
一.Docker的性质 Docker的组成其实很简单.你需要搭建registry,专属于你自己的私有仓库,然后就是docker的镜像和docker的容器.Docker的镜像,就类似与windos的系统 ...
- jQuery使用(十四):extend()方法
浅层克隆 深层克隆 扩展方法 一.extend的基本使用 语法: $.extend( target [, object1 ] [, objectN ] ) $.extend( [deep ], tar ...
- Python复习笔记(十一)TCP/IP协议
1. TCP/IP协议简介 帧头: mac地址, 网卡上的序列号 2. wireshark使用 分析一个数据是否发送, 是否是网络问题 ip.dst == 192.168.0.137 and udp ...
- 使用C语言中qsort()函数对浮点型数组无法成功排序的问题
一 写在开头 1.1 本节内容 本节主要内容是有关C语言中qsort()函数的探讨. 二 问题和相应解决方法 qsort()是C标准库中的一个通用的排序函数.它既能对整型数据进行排序也能对浮点型数据进 ...
- [物理学与PDEs]第1章第8节 静电场和静磁场 8.2 稳定电流的电场
1. 此时, Maxwell 方程组为 $$\beex \bea \Div{\bf D}&=\rho_f,\\ \rot {\bf E}&={\bf 0},\\ \Div{\bf B} ...
- 高并发秒杀系统--Service接口设计与实现
[DAO编写之后的总结] DAO层 --> 接口设计 + SQL编写 DAO拼接等逻辑 --> 统一在Service层完成 [Service层的接口设计] 1.接口 ...
- jQuery UI弹出新窗体
借助jqueryUI 的Dialog 在隐藏的div中嵌入Iframe 改变iframe的路径 如果项目经常用到弹出新窗体,则利用模板,把此代码和html 放入父页面中,实现父级调用, <in ...
- Xvector in Kaldi nnet3
Xvector nnet Training of Xvector nnet Xvector nnet in Kaldi Statistics Extraction Layer in Kaldi ...
- 第四周结对项目总结及改进(ui/web)
项目介绍 随着社会科技的进步和多媒体教育的日益发展,越来越来的学生正在接受着新时代下的教育模式,而且手机.电脑等科技产品的普及以及其带来的更高效更便捷的模式 使得它们成为当代学生学习中的一种很好的学习 ...
- main 及Scanner
通过main方法的args数组可以从控制台获取一组字符串数据. 1.Scanner类用于扫描从控制台输入的数据,可以接收字符串和基本数据类型的数据. 2.Scanner类位于java.util.Sca ...