• stark


    ✘  list_view

    处理表格(默认是显示表结构的所有字段)

     1 list_display = self.get_list_display()
     2 # 4.1处理表头
     3 header_list = []
     4 if list_display:
     5     for multi_key in list_display:
     6         if isinstance(multi_key,FunctionType):  #判断 传入值是否为函数
     7             verbose_name = multi_key(self,obj=None,is_header=True)
     8         else:
     9             verbose_name = self.model_class._meta.get_field(multi_key).verbose_name
    10         header_list.append(verbose_name)
    11 else:
    12     header_list.append(self.model_class._meta.model_name)
    13 
    14 # 4.2处理表的内容
    15 data_list = queryset[pager.start:pager.end]
    16 
    17 body_list = []
    18 for row in data_list:  #row 是UserInfo object (1)
    19     row_list = []
    20 
    21     if list_display:
    22         for multi_key in list_display:
    23             if isinstance(multi_key,FunctionType):
    24                 row_list.append(multi_key(self,row,is_header=False,*args,**kwargs))
    25             else:
    26                 row_list.append(getattr(row,multi_key))  #获取UserInfo object (1)的属性
    27     else:
    28         row_list.append(row)
    29 
    30     body_list.append(row_list)

    为了能够扩展以后业务的功能(推出新的业务,高级用户可能要显示多的列或者新的功能),我们可以针对某张表进行自定义修改定制。只需在自己的Handler子类重写此方法

    这是StarkHandler类的方法
    1
    list_display = [] 2 def get_list_display(self): 3 """ 4 获取页面上应该显示的列,预留自定义扩展 5 :return: 6 """ 7 field_list = [] 8 field_list.extend(self.list_display) 9 return field_list

    在上面方法的架构基础下,实现以往对表〔编辑〕〔删除〕的基本功能,同样放在基类中

    如图           

     1 def display_edit(self,obj=None,is_header=None):
     2     """
     3     生成<编辑>a标签
     4     :param obj:
     5     :param is_header:
     6     :return:
     7     """
     8     if is_header:
     9         return "编辑操作"
    10     change_url = self.reverse_change_url(pk=obj.pk)
    11     return mark_safe('<a href="%s">编辑</a>'%change_url)
    12 
    13 def display_delete(self,obj=None,is_header=None):
    14     """
    15     生成<删除>a标签
    16     :param obj:
    17     :param is_header:
    18     :return:
    19     """
    20     if is_header:
    21         return "删除操作"
    22     delete_url = self.reverse_delete_url(pk=obj.pk)
    23     return mark_safe('<a href="%s">删除</a>'% delete_url)

    示例:

     1 #models.py下的Major类:
     2 #class Major(models.Model):
     3 #    title = models.CharField(verbose_name='专业',max_length=32)
     4 #
     5 #    def __str__(self):
     6 #        return self.title
     7 
     8 #该model类view函数下,继承StarkHanler,list_display[字段+方法]:
     9 from stark.service.v1 import StarkHandler
    10 
    11 class MajorHandler(StarkHandler):
    12     list_display = ['title',StarkHandler.display_edit,StarkHandler.display_delete]
    View Code

    但是,如果表结构里有choice字段呢?

    则需要使用obj.get_字段名_display 获取orm对象的信息。解决的话,同样写一个方法放在基类,以后提取choice字段的信息直接使用

     这里不是StarkHandler类。
    1
    def get_choice_text(title,field): 2 """ 3 对于Stark组件中定义列时,choice如果想要显示中文信息,调用此方法即可 4 :param title: 表头名称(自定义) 5 :param field: 字段名称(需要提取的) 6 :return: 7 """ 8 def inner(self,obj=None,is_header=None): 9 if is_header: 10 return title 11 method = "get_%s_display" %field 12 return getattr(obj,method)() 13 14 return inner

    Exa: list_display=[get_choice_text('性别','gender')]

    表结构里有manytomany的字段呢?

     1 def get_m2m_text(title, field):
     2     """
     3     对于Stark组件中定义列时,显示m2m文本信息
     4     :param title: 表头名称
     5     :param field: 字段名称
     6     :return:
     7     """
     8 
     9     def inner(self, obj=None, is_header=None, *args, **kwargs):
    10         if is_header:
    11             return title
    12         queryset = getattr(obj, field).all()
    13         text_list = [str(row) for row in queryset]
    14         return ','.join(text_list)
    15 
    16     return inner

    Exa: list_display=[get_m2m_text('授课老师','teacher')]

    当存储数据多了呢?滚动查找所有数据?

    这边借鉴了前辈所写的分页组件

      1 """
      2 分页组件
      3 """
      4 from django.utils.safestring import mark_safe
      5 
      6 class Pagination(object):
      7     def __init__(self, current_page, all_count, base_url, query_params, per_page=20, pager_page_count=11):
      8         """
      9         分页初始化
     10         :param current_page: 当前页码
     11         :param per_page: 每页显示数据条数
     12         :param all_count: 数据库中总条数
     13         :param base_url: 基础URL
     14         :param query_params: QueryDict对象,内部含所有当前URL的原条件
     15         :param pager_page_count: 页面上最多显示的页码数量
     16         """
     17         self.base_url = base_url
     18         try:
     19             self.current_page = int(current_page)
     20             if self.current_page <= 0:
     21                 raise Exception()
     22         except Exception as e:
     23             self.current_page = 1
     24         self.query_params = query_params
     25         self.per_page = per_page
     26         self.all_count = all_count
     27         self.pager_page_count = pager_page_count
     28         pager_count, b = divmod(all_count, per_page)
     29         if b != 0:
     30             pager_count += 1
     31         self.pager_count = pager_count
     32 
     33         half_pager_page_count = int(pager_page_count / 2)
     34         self.half_pager_page_count = half_pager_page_count
     35 
     36     @property
     37     def start(self):
     38         """
     39         数据获取值起始索引
     40         :return:
     41         """
     42         return (self.current_page - 1) * self.per_page
     43 
     44     @property
     45     def end(self):
     46         """
     47         数据获取值结束索引
     48         :return:
     49         """
     50         return self.current_page * self.per_page
     51 
     52     def page_html(self):
     53         """
     54         生成HTML页码
     55         :return:
     56         """
     57         # 如果数据总页码pager_count<11 pager_page_count
     58         if self.pager_count < self.pager_page_count:
     59             pager_start = 1
     60             pager_end = self.pager_count
     61         else:
     62             # 数据页码已经超过11
     63             # 判断: 如果当前页 <= 5 half_pager_page_count
     64             if self.current_page <= self.half_pager_page_count:
     65                 pager_start = 1
     66                 pager_end = self.pager_page_count
     67             else:
     68                 # 如果: 当前页+5 > 总页码
     69                 if (self.current_page + self.half_pager_page_count) > self.pager_count:
     70                     pager_end = self.pager_count
     71                     pager_start = self.pager_count - self.pager_page_count + 1
     72                 else:
     73                     pager_start = self.current_page - self.half_pager_page_count
     74                     pager_end = self.current_page + self.half_pager_page_count
     75 
     76         page_list = []
     77 
     78         if self.current_page <= 1:
     79             prev = '<li><a href="#">上一页</a></li>'
     80         else:
     81             self.query_params['page'] = self.current_page - 1
     82             prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url, self.query_params.urlencode())
     83         page_list.append(prev)
     84         for i in range(pager_start, pager_end + 1):
     85             self.query_params['page'] = i
     86             if self.current_page == i:
     87                 tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % (
     88                     self.base_url, self.query_params.urlencode(), i,)
     89             else:
     90                 tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,)
     91             page_list.append(tpl)
     92 
     93         if self.current_page >= self.pager_count:
     94             nex = '<li><a href="#">下一页</a></li>'
     95         else:
     96             self.query_params['page'] = self.current_page + 1
     97             nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),)
     98         page_list.append(nex)
     99         page_str = "".join(page_list)
    100         return mark_safe(page_str)
    View Code

    Combine▼

     list_view下的分页功能:
    1
    all_count = queryset.count() 2 query_params = request.GET.copy() # ?=page=1&name='李四' 3 query_params._mutable = True #query_params['page']默认是不可以修改的 4 5 pager = Pagination( 6 current_page=request.GET.get('page'), 7 all_count=all_count, 8 base_url=request.path_info, 9 query_params=query_params, 10 per_page=self.per_page_count, 11 )

    ✘  add_view

    如图,    

    为了能够在模板循环展示表单数据、错误信息等,我们得创建forms.ModelForm对象,然后把form对象传递过去。

    但是每张表model_class所产生的form对象是不一样的,因此不同请求进来都得创建一个ModelForm,这样就太不方便了

    解决: 

    1 class DynamicModelForm(forms.ModelForm):
    2     class Meta:
    3         model = self.model_class  不把model表写死了,应该是动态的,即需要访问的model类
    4         fields = "__all__"

    在这基础下,封装成为一个方法,往后需要产生form对象时,代入model类,直接调用。

     1     model_form = False
     2     def get_model_form(self):
     3         if self.model_form:   #预留勾子,拓展或者自定义定制覆盖即可
     4             return self.model_form
     5 
     6         class DynamicModelForm(forms.ModelForm):
     7             class Meta:
     8                 model = self.model_class
     9                 fields = "__all__"
    10 
    11             def __init__(self, *args, **kwargs):
    12                 super(DynamicModelForm, self).__init__(*args, **kwargs)
    13                 # 统一给ModelForm生成字段添加样式
    14                 for name, field in self.fields.items():
    15                     field.widget.attrs['class'] = 'form-control'
    16 
    17         return DynamicModelForm

    如果有需求想让form对象多一行确认密码,或者控制显示的行呢?

    前者可以在子类重写ModelForm,而后者我们则需为form.save()预留勾子,方便拓展或重写覆盖。

    1     def save(self,request,form,is_update,*args,**kwargs):
    2 form.save()

    实现save基操下,想到如果在点击添加按钮的时候,URL本身带有 /?page=1的参数下,执行添加操作后,理应返回原来页面的时候带回这个参数。

    这里,简单地理一下。

    1.在进入添加路由时,我们先把参数部分urlencode(),然后把数据作为键值"_filter"的value值,最后urlencode() 作为新的参数。

     1     def reverse_add_url(self,**kwargs):
     2         name = "%s:%s" % (self.site.namespace, self.get_add_url_name)  #stark:Web_customer_public_list
     3         url = reverse(name,kwargs=kwargs)
     4 
     5         if not self.request.GET:
     6             add_url = url
     7         else:
     8             param = self.request.GET.urlencode()  # page=1
     9 
    10             new_query_dict = QueryDict(mutable=True)
    11             new_query_dict['_filter'] = param  # <QueryDict: {'_filter': ['page=1']}>
    12 
    13             add_url = "%s?%s" % (url, new_query_dict.urlencode(()))
    14 
    15         return add_url

    2.类似地,添加完后 redirect 回原来页面并带回参数

     1     def reverse_list_url(self,**kwargs):
     2         name = "%s:%s" % (self.site.namespace, self.get_list_url_name)
     3         url = reverse(name,kwargs=kwargs)
     4         if not self.request.GET:
     5             list_url = url
     6         else:
     7             param = self.request.GET.get('_filter')
     8             # print(param)  #page=1
     9             if not param:
    10                 return redirect(url)
    11             list_url = "%s?%s" % (url, param)
    12 
    13         return list_url

    所有的铺垫下,添加视图方法基本完成。

     1     def add_view(self,request,*args,**kwargs):
     2         """
     3         添加视图
     4         :param request:
     5         :return:
     6         """ 
     7         model_form = self.get_model_form()
     8         if request.method == 'GET':
     9             form = model_form
    10             return render(request, 'change.html', {'form': form})
    11 
    12         form = model_form(data=request.POST)
    13         if form.is_valid():
    14             response =  self.save(request,form,False,*args,**kwargs)
    15             return response or redirect(self.reverse_list_url(**kwargs))
    16         return render(request,'change.html',{'form':form})

    ✘  change_view

     基本跟添加视图一样,只是form对象在表单默认显示数据

     1     def get_change_object(self, request, pk, *args, **kwargs):
     2         return self.model_class.objects.filter(pk=pk).first()
     3 
     4     def change_view(self,request,pk,*args,**kwargs):
     5         """
     6         编辑视图
     7         :param request:
     8         :param pk:
     9         :return:
    10         """
    11         checked_obj = self.get_change_object(request, pk, *args, **kwargs)
    12 
    13         if not checked_obj: 
    14             return render(request,'rbacerror.html')
    15 
    16         model_form = self.get_model_form()
    17         if request.method == 'GET':
    18             form = model_form(instance=checked_obj)
    19             return render(request, 'change.html', {'form': form})
    20 
    21         form = model_form(data=request.POST,instance=checked_obj)
    22         if form.is_valid():
    23             response = self.save(request, form, True, *args, **kwargs)
    24             return response or redirect(self.reverse_list_url(**kwargs))
    25         return render(request, 'change.html', {'form': form})

    ✘  delete_view

    基本跟添加视图一样。

    这里继承以往为了防止用户删除数据时小手一抖,做出的确认选择按钮

     1     def delete_object(self, request, pk, *args, **kwargs):
     2         self.model_class.objects.filter(pk=pk).delete()
     3 
     4     def delete_view(self,request,pk,*args,**kwargs):
     5         """
     6         删除视图
     7         :param request:
     8         :param pk:
     9         :return:
    10         """
    11         checked_obj  = self.model_class.objects.filter(pk=pk).first()
    12         if not checked_obj:
    13             return render(request,'rbacerror.html',)
    14 
    15         list_url = self.reverse_list_url(**kwargs)
    16         if request.method == 'GET':
    17             return render(request,'delete.html',{'list_url':list_url})
    18 
    19         response = self.delete_object(request, pk, *args, **kwargs)
    20         return response or redirect(list_url)
  • 相关阅读:
    frame、center和bounds
    UILabel
    UIColor
    Url_Filter(Code)
    listView介绍
    C# 常用正则
    C++指针的概念
    指针所具有的四个要素:
    windows_sendEmail
    工作笔记
  • 原文地址:https://www.cnblogs.com/steven2020/p/10708283.html
Copyright © 2020-2023  润新知