Xadmin相关实现

一,保存搜索条件(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)
批量操作中相关视图函数的实现

  1. 实现的一个基本思路:

首先,在默认的基础配置类中一定要有一个可设置批量操作的属性,并规定一个实现的方式,自定义的一个格式。
在后端做一个基础的处理,如果用户为配置该属性,则默认实现批量删除的功能,如果用户自定义了,则优先显示用户自定义的属性,再在最后展示默认的批量删除操作
构建在前端的展示方式:使用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

批量操作中相关模板部分的实现

{% csrf_token %}
上一篇:C# Socket网络编程


下一篇:Unity 通用透明物体漫反射Shader(双面渲染&多光源&光照衰减&法线贴图&凹凸透明度控制)