一,保存搜索条件(Save search conditions)
kept conditions(保存条件)的应用场景比较常见,在我们查询时,可以实现多条件的筛选查询,比如:在淘宝上,选择了其中的一个条件后,我们可以继续选择其他的一些过滤条件,然后就可以实现多条件的查询。
那么代码时怎么实现的呢?
我们在用户提交查询条件请求时,一般都是GET请求,在相关路径后拼上?条件的形式,在Django中,我们在后端接收是通过request.GET这个属性得到所有的条件,在Django中,request.GET是一个QueryDict类型的数据。<QueryDict: {}>
访问一个请求
print(request.GET,type(request.GET))
<QueryDict: {}> <class 'django.http.request.QueryDict'>
我们点击它的源码,看看这个QueryDict的内部都做了些什么(from django.http.request import QueryDict)
class QueryDict(MultiValueDict):
_mutable = True
_encoding = None
def __init__(self, query_string=None, mutable=False, encoding=None):
super(QueryDict, self).__init__()
if not encoding:
encoding = settings.DEFAULT_CHARSET
self.encoding = encoding
query_string = query_string or ''
self._mutable = mutable
这是截取的QueryDict中的一部分,在QueryDict中,有一个属性_mutable,这个值是True时,表示QueryDict可以被修改,否则表示无法被修改,通过源码可以看出,QueryDict在实例一个对象时,self._mutable是False,是不可修改的
而request.GET是一个QueryDict的实例,所以,request.GET是不可以被修改的
如果我们要修改或者添加request.GET中的值时,我们必须设置一个属性值request.GET._mutable=True,这样就可以修改了。
那我们如何保存搜索条件呢,要保存搜索条件,我们首先要得到用户访问时携带的条件,那这个条件怎么获取呢?
在Django中,提供了一个方法用于或者请求的字符串格式的搜索条件,这个方法就是:request.GET.urlencode()
比如:
我们访问路径:http://127.0.0.1:8000/Xadmin/demo/order/?id=1&page=2
得到的是这个
print(request.GET,request.GET.urlencode())
<QueryDict: {'id': ['1'], 'page': ['2']}> id=1&page=2
通过这个方法我们可以把获取的这个参数拼接到相应路径后面。
如果我们对request.GET这个参数修改时,我们最好是copy一个同样的数据,而不是在原数据上进行修改,这样可以保证数据的安全性,因为在其他地方,我们肯定还会使用这个request.GET这个参数。
注意:在copy时,我们不需要设置_mutable=True这个参数就可以修改,因为Django已经为我们想到了这个情况,在QueryDict的源码中,对这两个copy有重写,默认的参数就是mutable=True,所以我们使用copy后,可以直接对原数据修改。
def copy(self):
result = self.class('', mutable=True, encoding=self.encoding)
for key, value in six.iterlists(self):
result.setlist(key, value)
return result
def __deepcopy__(self, memo):
result = self.__class__('', mutable=True, encoding=self.encoding)
memo[id(self)] = result
for key, value in six.iterlists(self):
result.setlist(copy.deepcopy(key, memo), copy.deepcopy(value, memo))
return result
所以,我们在取到这个值时,直接对这个值进行copy,然后在做修改
params = request.GET
import copy
params = copy.deepcopy(params) #可以直接对这个值做修改
params["要修改的值"] = value
二、搜索框功能的实现(search_fields)
相关实现的视图函数部分
配置类的实现代码
from django.db.models import Q
from django.shortcuts import HttpResponse, render
配置类
class ModelXadmin(object):
# 配置类中默认的搜索内容
search_fields = []
def __init__(self, model, site):
self.model = model
self.site = site
self.model_name = ""
self.app_name = ""
# 将搜索的实现单独的封装到一个函数中
def get_search_condition(self, request):
# 实例化一个Q对象
search_condition = Q()
# 设置多条件搜索的关系为或
search_condition.connector = "or"
# print("search_fields", self.search_fields) # ["title","price"]
# 获取输入的搜索内容
key_word = request.GET.get('q')
if key_word: # 对搜索内容判断,如果为空,models.XXX.objects.filter()时 会报错
for search_field in self.search_fields:
search_condition.children.append((search_field + "__icontains", key_word))
return search_condition
# 查看视图函数
def list_view(self, request):
"""
self.model: 用户访问哪张表,self.model就是谁
data_list: 查看表下的数据
:param request:
:return:
"""
search_condition = self.get_search_condition(request)
data_list = self.model.objects.filter(search_condition)
model_name = self.model._meta.model_name
return render(request, 'list_view.html', locals())
备注:示例化Q对象值为空时,filter(Q对象) 等同于all()
相关实现的模板部分
{% if search_fields %}
{% endif %}
三、批量操作的实现(actions)
批量操作中相关视图函数的实现
- 实现的一个基本思路:
首先,在默认的基础配置类中一定要有一个可设置批量操作的属性,并规定一个实现的方式,自定义的一个格式。
在后端做一个基础的处理,如果用户为配置该属性,则默认实现批量删除的功能,如果用户自定义了,则优先显示用户自定义的属性,再在最后展示默认的批量删除操作
构建在前端的展示方式:使用select的下拉框展示option中value为批量操作的方法名(函数名)(备注:因为在前端中不能使用__name__这个属性,所以在后端构建),文本内容为对这个方法的描述内容
将所有的有效控件放置在一个form表单中,发送post请求,(有效控件包括:select标签中的option标签:所有的批量操作的方法action,表单中的每行的checkbox,代表该行数据的pk值)
取到对应的方法名(字符串形式的)和对应的数据,通过反射执行该方法,进行相应批量操作
返回处理结果,或者直接展示当前页面
2.具体实现代码:
class ModelXadmin(object):
actions=[]
# 默认的批量删除操作,默认出入两个参数:1.request 2.包含所有执行批量操作数据的queryset集
def patch_delete(self,request,queryset):
queryset.delete()
# 方法的描述内容
patch_delete.short_description="批量删除"
# action的基础处理 优先展示用户的配置信息
def get_actions(self):
temp=[]
temp.extend(self.actions)
temp.append(self.patch_delete)
return temp
def __init__(self,model,site):
self.model=model
self.site=site
self.model_name=""
self.app_name=""
构建展示方式:
class ShowList(object):
def init(self,config,request,data_list):
self.config=config
self.data_list=data_list
self.request=request
# 封装的展示类中
self.actions=self.config.get_actions()
# 处理前端的展示信息 构建一个包含每一个action字典的列表
def new_actions(self):
temp=[]
for action in self.actions:
temp.append({
"name":action.__name__,
"desc":action.short_description
})
return temp
批量操作中相关模板部分的实现