博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
strak组件(10):批量操作
阅读量:6624 次
发布时间:2019-06-25

本文共 16770 字,大约阅读时间需要 55 分钟。

效果图:

 

批量删除只是一个例子,可以根据需求定制自己想要的批量操作。

 

新增函数

def get_action_list(self)  钩子方法,获取要处理的批量操作的函数def action_multi_delete(self, request, *args, **kwargs)  批量删除

一、strak组件

import functoolsfrom types import FunctionTypefrom django import formsfrom django.db.models import Qfrom django.http import QueryDictfrom django.urls import re_pathfrom django.utils.safestring import mark_safefrom django.shortcuts import HttpResponse, render, reverse, redirectfrom stark.utils.pagination import Paginationclass StarkModelForm(forms.ModelForm):    def __init__(self, *args, **kwargs):        super(StarkModelForm, self).__init__(*args, **kwargs)        # 统一给ModelForm生成字段添加样式        for name, field in self.fields.items():            field.widget.attrs['class'] = 'form-control'def get_choice_text(title, field):    """    对于Stark组件中定义列时,choice如果想要显示中文信息,调用此方法即可。    :param title: 希望页面显示的表头    :param field:  字段名称    :return:    """    def inner(self, obj=None, is_header=None):        if is_header:            return title        method = f"get_{field}_display"        return getattr(obj, method)()        # GENDER_CHOICES = ((MALE, '男'),(FEMALE, '女'),)        # 对于choice字段,如果想获取获取第二个值,可以通过:对象.get_字段名_display()    return innerclass StarkHandler(object):    list_display = []    order_list = []    search_list = []    per_page_data = 10    has_add_btn = True    model_form_class = None    list_template = None    add_template = None    edit_template = None    delete_template = None    action_list = []    def __init__(self, site, model_class, prev):        self.site = site        self.model_class = model_class        self.prev = prev        self.request = None    def display_checkbox(self, obj=None, is_header=None, *args, **kwargs):        """        复选框        :param obj:        :param is_header:        :param args:        :param kwargs:        :return:        """        if is_header:            return '选择'        return mark_safe(f'')    def display_edit(self, obj=None, is_header=None, *args, **kwargs):        """        自定义页面显示的列(表头和内容)        :param obj:        :param is_header:        :return:        """        if is_header:            return '编辑'        name = f'{self.site.namespace}:{self.get_edit_url_name}'        return mark_safe(f'编辑')    def display_delete(self, obj=None, is_header=None, *args, **kwargs):        if is_header:            return '删除'        name = f'{self.site.namespace}:{self.get_delete_url_name}'        return mark_safe(f'删除')    def get_list_display(self, request, *args, **kwargs):        """        获取页面上应该显示的列,预留的自定义扩展,例如:以后根据用户的不同显示不同的列        :return:        """        value = []        value.extend(self.list_display)        return value    def get_search_list(self):        return self.search_list    def get_add_btn(self, *args, **kwargs):        if self.has_add_btn:            return f'添加'    def get_model_form_class(self, request, *args, **kwargs):        if self.model_form_class:            return self.model_form_class        class DynamicModelForm(StarkModelForm):            class Meta:                model = self.model_class                fields = '__all__'        return DynamicModelForm    def get_order_list(self):        return self.order_list or ['-id', ]    def get_action_list(self):        return self.action_list    def action_multi_delete(self, request, *args, **kwargs):        """        批量删除(如果想要定制执行成功后的返回值,那么就为action函数设置返回值即可)        :param request:        :param args:        :param kwargs:        :return:        """        pk_list = request.POST.getlist('pk')        self.model_class.objects.filter(id__in=pk_list).delete()    action_multi_delete.text = '批量删除'    def list_view(self, request, *args, **kwargs):        """        列表页面        :param request:        :return:        """        # 1. 处理Action        action_list = self.get_action_list()        action_dict = {func.__name__: func.text for func in action_list}        if request.method == 'POST':            action_func_name = request.POST.get('action')            if action_func_name and action_func_name in action_dict:                action_response = getattr(self, action_func_name)(request, *args, **kwargs)                if action_response:                    return action_response        # 2. 处理搜索        # 搜索列表写ORM语句,如:['name__contains','email__contains','id__gt','gender']        search_list = self.get_search_list()        search_value = request.GET.get('q', '')        conn = Q()        conn.connector = 'OR'  # 通过or链接        if search_value:            for item in search_list:                conn.children.append((item, search_value))  # conn.children.append('name__contains','张三')        # 3. 获取排序        order_list = self.get_order_list()        queryset = self.model_class.objects.filter(conn).order_by(*order_list)        # 4. 分页处理        all_count = queryset.count()        query_params = request.GET.copy()  # 深copy        query_params._mutable = True  # query_params默认不可修改        pager = Pagination(            current_page=request.GET.get('page'),            all_count=all_count,            base_url=request.path_info,            query_params=query_params,            per_page_data=self.per_page_data,        )        data_list = queryset[pager.start:pager.end]        # 5. 处理表格        list_display = self.get_list_display(request, *args, **kwargs)  # 会优先调用UserInfoHandler里的get_list_display()方法。        # 5.1 处理表格的表头        header_list = []        if list_display:            for field_or_func in list_display:                if isinstance(field_or_func, FunctionType):                    verbose_name = field_or_func(self, obj=None, is_header=True)                else:                    verbose_name = self.model_class._meta.get_field(field_or_func).verbose_name                header_list.append(verbose_name)        else:            header_list.append(self.model_class._meta.model_name)  # 如果用户没有填写list_display,就显示表名        # 5.2 处理表的内容        body_list = []        for obj in data_list:            tr_list = []            if list_display:                for field_or_func in list_display:                    if isinstance(field_or_func, FunctionType):                        tr_list.append(field_or_func(self, obj, is_header=False, *args, **kwargs))                    else:                        tr_list.append(getattr(obj, field_or_func))            else:                tr_list.append(obj)  # 如果用户没有填写list_display,就显示表对象,所以表类要定义__str__方法            body_list.append(tr_list)        # 6 添加按钮        add_btn = self.get_add_btn(*args, **kwargs)        context = {            'data_list': data_list,            'header_list': header_list,            'body_list': body_list,            'pager': pager,            'add_btn': add_btn,            'search_list': search_list,            'search_value': search_value,            'action_dict': action_dict,        }        return render(request, self.list_template or 'stark/data_list.html', context)    def save(self, form, is_update=False, *args, **kwargs):        """        在使用ModelForm保存数据之前预留的钩子方法        :param form:        :param is_update:        :return:        """        form.save()    def add_view(self, request, *args, **kwargs):        """        添加页面        :param request:        :return:        """        model_form_class = self.get_model_form_class(request, *args, **kwargs)        if request.method == 'GET':            form = model_form_class()            return render(request, 'stark/change.html', {
'form': form}) form = model_form_class(data=request.POST) if form.is_valid(): self.save(form, False, *args, **kwargs) # 在数据库保存成功后,跳转回列表页面(携带原来的参数)。 return redirect(self.reverse_list_url(*args, **kwargs)) return render(request, self.add_template or 'stark/change.html', {
'form': form}) def edit_view(self, request, pk, *args, **kwargs): """ 编辑页面 :param request: :return: """ current_edit_object = self.model_class.objects.filter(pk=pk).first() if not current_edit_object: return HttpResponse('要修改的数据不存在,请重新选择') model_form_class = self.get_model_form_class(request, *args, **kwargs) if request.method == 'GET': form = model_form_class(instance=current_edit_object) return render(request, 'stark/change.html', {
'form': form}) form = self.model_form_class(data=request.POST, instance=current_edit_object) if form.is_valid: self.save(form, True, *args, **kwargs) # 在数据库保存成功后,跳转回列表页面(携带原来的参数) return redirect(self.reverse_list_url(*args, **kwargs)) return render(request, 'stark/change.html', {
'form': form}) def delete_view(self, request, pk, *args, **kwargs): """ 删除页面 :param request: :param pk: :return: """ original_list_url = self.reverse_list_url(*args, **kwargs) if request.method == 'GET': return render(request, 'stark/delete.html', {
'cancel': original_list_url}) self.model_class.objects.filter(pk=pk).delete() return redirect(original_list_url) def get_url_name(self, params): app_label, model_name = self.model_class._meta.app_label, self.model_class._meta.model_name if self.prev: return f'{app_label}_{model_name}_{self.prev}_{params}' return f'{app_label}_{model_name}__{params}' @property def get_list_url_name(self): """ 获取列表页面URL的name :return: """ return self.get_url_name('list') @property def get_add_url_name(self): """ 获取添加页面URL的name :return: """ return self.get_url_name('add') @property def get_edit_url_name(self): """ 获取编辑页面URL的name :return: """ return self.get_url_name('edit') @property def get_delete_url_name(self): """ 获取删除页面URL的name :return: """ return self.get_url_name('delete') def reverse_common_url(self, name, *args, **kwargs): """ 生成带有原搜索条件的URL :param name: url :param args: :param kwargs: :return: """ name = f'{self.site.namespace}:{name}' base_url = reverse(name, args=args, kwargs=kwargs) if not self.request.GET: reverse_url = base_url else: params = self.request.GET.urlencode() new_query_dict = QueryDict(mutable=True) new_query_dict['_filter'] = params reverse_url = f'{base_url}?{new_query_dict.urlencode()}' return reverse_url def reverse_add_url(self, *args, **kwargs): """ 带有原搜索条件的增加URL :param args: :param kwargs: :return: """ return self.reverse_common_url(self.get_add_url_name, *args, **kwargs) def reverse_edit_url(self, *args, **kwargs): """ 带有原搜索条件的编辑URL :param args: :param kwargs: :return: """ return self.reverse_common_url(self.get_edit_url_name, *args, **kwargs) def reverse_delete_url(self, *args, **kwargs): """ 带有原搜索条件的删除URL :param args: :param kwargs: :return: """ return self.reverse_common_url(self.get_delete_url_name, *args, **kwargs) def reverse_list_url(self, *args, **kwargs): name = f'{self.site.namespace}:{self.get_list_url_name}' base_url = reverse(name, args=args, kwargs=kwargs) params = self.request.GET.get('_filter') if not params: return base_url return f'{base_url}?{params}' def wrapper(self, func): """ 当每一个request请求进来的时候,把request赋值给类的数据属性self.request :param func: request请求对应的视图函数 :return: """ @functools.wraps(func) # 保留原函数的原信息,写装饰器建议写上这个。 def inner(request, *args, **kwargs): self.request = request return func(request, *args, **kwargs) return inner def get_urls(self): patterns = [ re_path(r'^list/$', self.wrapper(self.list_view), name=self.get_list_url_name), re_path(r'^add/$', self.wrapper(self.add_view), name=self.get_add_url_name), re_path(r'^edit/(\d+)/$', self.wrapper(self.edit_view), name=self.get_edit_url_name), re_path(r'^delete/(\d+)/$', self.wrapper(self.delete_view), name=self.get_delete_url_name), ] patterns.extend(self.extra_urls()) return patterns def extra_urls(self): return []class StarkSite(object): def __init__(self): self._registry = [] self.app_name = 'stark' self.namespace = 'stark' def register(self, model_class, handler_class=None, prev=None): """ :param model_class: 是models中的数据库表对应的类。 :param handler_class: 处理请求的视图函数所在的类 :param prev: 生成URL的前缀 :return: """ if not handler_class: handler_class = StarkHandler self._registry.append( {
'model_class': model_class, 'handler': handler_class(self, model_class, prev), 'prev': prev}) def get_urls(self): patterns = [] for item in self._registry: model_class = item['model_class'] handler = item['handler'] prev = item['prev'] app_name, model_name = model_class._meta.app_label, model_class._meta.model_name if prev: patterns.append( re_path(rf'^{app_name}/{model_name}/{prev}/', (handler.get_urls(), None, None))) else: patterns.append( re_path(rf'^{app_name}/{model_name}/', (handler.get_urls(), None, None))) return patterns @property def urls(self): return self.get_urls(), self.app_name, self.namespacesite = StarkSite()

 

二、业务代码

from stark.service.core_func import site, StarkHandler, StarkModelForm, get_choice_textfrom web import modelsclass UserInfoModelForm(StarkModelForm):    class Meta:        model = models.UserInfo        fields = ['name', 'gender', 'classes', 'age', 'email']class DepartmentHandler(StarkHandler):    list_display = ['title']class UserInfoHandler(StarkHandler):    per_page_data = 5    order_list = ['gender']    model_form_class = UserInfoModelForm    search_list = ['name__contains', 'email__contains', ]    action_list = [StarkHandler.action_multi_delete, ]    list_display = [        StarkHandler.display_checkbox,        'name',        get_choice_text('性别', 'gender'),        get_choice_text('班级', 'classes'),        'age', 'email', 'department',        StarkHandler.display_edit,        StarkHandler.display_delete,    ]    def save(self, form, is_update=False, *args, **kwargs):        form.instance.department_id = 1        form.save()site.register(models.Department, DepartmentHandler)  # 给部门的url增加了前缀:/stark/web/department/private/site.register(models.UserInfo, UserInfoHandler)

 

三、模板渲染

{% extends 'layout.html' %}{% block css %}    
{% endblock css %}{% block content %}
{% if search_list %}
{% endif %}
{% csrf_token %} {% if action_dict %}
{% endif %}
{% if add_btn %}
{
{ add_btn|safe }}
{% endif %}
{% for item in header_list %}
{% endfor %}
{% for row in body_list %}
{% for ele in row %}
{% endfor %}
{% endfor %}
{ { item }}
{ { ele }}
{% endblock content %}

 

转载于:https://www.cnblogs.com/lshedward/p/10590714.html

你可能感兴趣的文章
【Solidity】2.合约的结构体 - 深入理解Solidity
查看>>
《C语言及程序设计》实践参考——二分法解方程
查看>>
java thread中的wait()和notify()
查看>>
2016最新搜索引擎优化(SEO)重点要素
查看>>
当Web访问性能出现问题,如何深探?
查看>>
【IOS-COCOS2D-X 游戏开发之二】【必看篇】总结阐述COCOS2D-X与COCOS2D-IPHONE区别;
查看>>
eoLinker-API_Shop_通讯服务类API调用的代码示例合集:短信服务、手机号归属地查询、电信基站查询等...
查看>>
前端面试回忆录 - 滴滴篇 - 凉面
查看>>
jxl导入Excel 切割List 并使用MyBatis批量插入数据库
查看>>
小程序开发总结
查看>>
Tomcat监听器设计思路
查看>>
管理ORACLE实例
查看>>
Confluence 6 MySQL 数据库设置准备
查看>>
Ruby 中 0/0.0 = NaN
查看>>
JEESNS数据库表设计结构
查看>>
JavaScript学习笔记:判断变量是否为undefined,判断变量和函数是否声明
查看>>
局域网访问Apache服务器
查看>>
JavaScript 闭包
查看>>
Spark算子:RDD行动Action操作(3)–aggregate、fold、lookup
查看>>
java获取当前时间前一周、前一月、前一年的时间
查看>>