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进行计算 ,返回一个聚合值的字典. ...
随机推荐
- UE4渲染笔记
Lightmass 实时渲染光影效果对性能有很大影响,可利用lightmass预先生成光影贴图,然后在游戏中使用. 将场景光照结果完全烘焙到模型贴图上,从而完完全全的假冒现实光照效果. 文档上是 li ...
- spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一)
最近在学习的时候,发现微服务架构中,假如只有一个注册中心,那这个注册中心挂了可怎么办,这样的系统,既不安全,稳定性也不好,网上和书上找了一会,发现这个spring cloud早就想到了,并帮我们解决了 ...
- Fatal error: cannot initialize AIO sub-system
在一台服务器中以各数据库的备份文件为数据文件启动多个MySQL实例供SQL Review使用.之前运行一直没有问题(最多的时候有23个MySQL实例同时运行),后来新配置了一台服务器,启动其对应的实例 ...
- CSS圆环百分比DEMO
<html> <head> <title>test</title><!--本DEMO参考http://www.cnblogs.com/jr1993 ...
- Mac 安装JRE 1.8
最近使用React Native,运行android版本时,需要jre 1.8,但是用oracle 的安装文件安装完毕后,在控制台java -version输出的还是 1.7版本.发现是环境变量没配对 ...
- web开篇
一.内容回顾 1.python基础 2.网络编程 3.并发编程 4.前端 5.数据库(MySQL) 二.今日概要 1.了解Web应用程序的本质 2.Django简介及安装使用 三.今日详细 1.最简单 ...
- hdu4352 数位dp+状态压缩+一个tip
按照nlogn求lis的方法,把lis的状态压缩了,每次新加一个数就把它右边第一个数的位置置为0,然后把这个数加进去 一个需要注意的地方,如果前面都是0,那么状态s中代表0的位置不可以是1,因为这种情 ...
- 在Pycharm中自动添加时间日期作者等信息
1.按照下面路径以此打开File→→Settings→→Editor→→File and code Templates 右侧找到Python Script,如下图 2.设置相关代码如下 ##!/usr ...
- 关于Idea模块化部署web项目,Web Resource Directories作用
问题由来:接到某个所谓“将web工程中部分代码抽出打包,但待打包部分代码还需要在现场部署时能做微调”的需求. 解决方法:将待打包部分代码作为一个module,让工程依赖该模块,满足抽离打包与现场可调试 ...
- 记录C#常用的代码片段
时间一久,常用的代码会有点忘记,还是贴在这里方便查找! 1.将信息写入文件中 //将字符串写入到文本中 void writeToText(string msg) { try { msg = DateT ...