zoukankan      html  css  js  c++  java
  • 附录:代码

    Files

     app01
    stark
    ┊----forms
    ┊----service
    ┊ ┊----__init__.py
    ┊ ┊----v1.py

    ┊----templates
    ┊----utils
    ┊ ┊----pagination.py

    ┊----__init__.py
    ┊----admin.py
    ┊----apps.py
    ....

    v1.py

      1 import functools
      2 from types import FunctionType
      3 from django.shortcuts import HttpResponse,render,reverse,redirect
      4 from django.conf.urls import url
      5 from django.utils.safestring import mark_safe
      6 from stark.utils.pagination import Pagination
      7 from django.http import QueryDict
      8 from django import forms
      9 from django.db.models import ManyToManyField,ForeignKey
     10 
     11 
     12 class SearchGroupRow(object):
     13     def __init__(self,title,queryset_or_tuple, option_object,query_dict):
     14         """
     15 
     16         :param title: 组合搜索的列名称
     17         :param queryset_or_tuple: 组合搜索关联获取到的数据
     18         :param option_object: Option对象
     19         :param query_dict: request.GET
     20         """
     21         self.title = title
     22         self.queryset_or_tuple = queryset_or_tuple
     23         self.option_object = option_object
     24         self.query_dict = query_dict
     25 
     26     def __iter__(self):
     27         yield mark_safe('<span class="search_group label label-default">%s</span>'%self.title)
     28         # yield self.title
     29         for item in self.queryset_or_tuple:
     30             text = self.option_object.get_text(item) #性别 /部门
     31             value = self.option_object.get_value(item) #'1' /技术部
     32 
     33             # url_dict = QueryDict(mutable=True)     一样的结果
     34             # url_dict[text] = value
     35             query_dict = self.query_dict.copy() #{'gender': ['1']}  #生成下面URL需要(1)
     36             query_dict._mutable = True
     37 
     38 
     39             if not self.option_object.is_multi:
     40                 request_value_list = query_dict.getlist(self.option_object.field) #获取GET数据 ['2']
     41 
     42                 query_dict[self.option_object.field] = value #生成下面URL需要(2)
     43                 # print(text,str(value),request_value_list)
     44                 if str(value) in request_value_list:
     45                     #通过去除 ?gender=2 重新赋值URL,实现再选取时 自动消失样式
     46                     query_dict.pop(self.option_object.field)
     47                     yield mark_safe('<a class="btn btn-danger active" href="?%s">%s</a>'%(query_dict.urlencode(),text))
     48                 else:
     49                     yield mark_safe('<a class="btn btn-default" href="?%s">%s</a>'%(query_dict.urlencode(),text))
     50 
     51             else:
     52                 multi_request_value_list =query_dict.getlist(self.option_object.field) #['1','2']
     53                 if str(value) in multi_request_value_list:
     54                     multi_request_value_list.remove(str(value))
     55                     query_dict.setlist(self.option_object.field,multi_request_value_list)
     56                     yield mark_safe('<a class="btn btn-danger active" href="?%s">%s</a>'%(query_dict.urlencode(),text))
     57                 else:
     58                     multi_request_value_list.append(str(value))
     59                     query_dict.setlist(self.option_object.field,multi_request_value_list)
     60                     yield mark_safe('<a class="btn btn-default" href="?%s">%s</a>'%(query_dict.urlencode(),text))
     61 
     62 class Option(object):
     63     def __init__(self,field,is_multi=False,db_condition=None,text_func=None,value_func=None):
     64         """
     65         :param field: 组合搜索关联的字段
     66         :param is_multi: 是否支持多选
     67         :param db_condition: 数据库关联查询时的条件
     68         :param text_func: 此函数用于组合搜索按钮 展示 文本或者图案
     69         :param value_func: 此函数用于显示组合搜索按钮值
     70         """
     71         self.field = field
     72         self.is_multi = is_multi
     73         if not db_condition:
     74             db_condition = {}
     75         self.db_condition = db_condition
     76         self.text_func = text_func
     77         self.value_func = value_func
     78 
     79         self.is_choice = False
     80 
     81     def get_db_condition(self):
     82         return self.db_condition
     83 
     84     def get_queryset_or_tuple(self,model_class,request,*args,**kwargs):
     85         """
     86 
     87         :param model_class:
     88         :param request:
     89         :param args:
     90         :param kwargs:
     91         :return:
     92         """
     93         field_object = model_class._meta.get_field(self.field) #choice:app01.UserInfo.gender #FK:app01.UserInfo.depart
     94 
     95         title = field_object.verbose_name
     96         if isinstance(field_object,ForeignKey) or isinstance(field_object,ManyToManyField):
     97             db_condition = self.get_db_condition()
     98             #### 返回的是QuerySet类型 ####
     99             #print(field_object.remote_field.model.objects.filter(**db_condition)) <QuerySet [<Depart: 技术部>, <Depart: 美术部>]>
    100             return SearchGroupRow(title,field_object.remote_field.model.objects.filter(**db_condition),self,request.GET) #self是Option类对象
    101         else:
    102             #### 获取choice中的数据 / 返回的是元祖类型 ####
    103             self.is_choice = True
    104             # print(field_object.choices)  ((1, '男'), (2, '女'))
    105             return SearchGroupRow(title,field_object.choices,self,request.GET)
    106 
    107     def get_text(self,field_object):
    108         if self.text_func:  #如果自定义了函数,则用自己的
    109             return self.text_func(field_object)
    110 
    111         if self.is_choice:
    112             return field_object[1]
    113 
    114         return str(field_object)
    115 
    116     def get_value(self,field_object):
    117         if self.value_func:  #自定制
    118             return self.value_func(field_object)
    119 
    120         if self.is_choice:
    121             return field_object[0]
    122 
    123         return field_object.pk
    124 
    125 
    126 def get_choice_text(title,field):
    127     """
    128     对于Stark组件中定义列时,choice如果想要显示中文信息,调用此方法即可
    129     :param title: 表头名称(自定义)
    130     :param field: 字段名称(需要提取的)
    131     :return:
    132     """
    133     def inner(self,obj=None,is_header=None):
    134         if is_header:
    135             return title
    136         method = "get_%s_display" %field
    137         return getattr(obj,method)()
    138 
    139     return inner
    140 
    141 def get_m2m_text(title, field):
    142     """
    143     对于Stark组件中定义列时,显示m2m文本信息
    144     :param title: 表头名称
    145     :param field: 字段名称
    146     :return:
    147     """
    148 
    149     def inner(self, obj=None, is_header=None, *args, **kwargs):
    150         if is_header:
    151             return title
    152         queryset = getattr(obj, field).all()
    153         text_list = [str(row) for row in queryset]
    154         return ','.join(text_list)
    155 
    156     return inner
    157 
    158 class StarkHandler(object):
    159 
    160     per_page_count = 10
    161     model_form = False
    162 
    163 
    164     def __init__(self,site,model_class,prev):
    165         """
    166         :param site: 一个对象
    167         :param model_class: 数据库表的类
    168         :param prev: url前缀
    169         """
    170         self.site = site
    171         self.model_class = model_class
    172         self.prev = prev
    173 
    174     list_display = []
    175     def get_list_display(self):
    176         """
    177         获取页面上应该显示的列,预留自定义扩展
    178         :return:
    179         """
    180         field_list = []
    181         field_list.extend(self.list_display)
    182         return field_list
    183 
    184     has_add_btn = True
    185     def get_add_btn(self,**kwargs):
    186         if self.has_add_btn:
    187             return mark_safe('<a href="%s" class="btn btn-danger">添加</a>'%self.reverse_add_url(**kwargs))
    188         return None
    189 
    190     action_list = []
    191     def get_action_list(self):
    192         """
    193         处理批量操作等自定义方法
    194         :return:
    195         """
    196         return self.action_list
    197 
    198     def get_queryset(self,**kwargs):
    199         return self.model_class.objects
    200 
    201     order_list = []
    202     def get_order_list(self):
    203         return self.order_list or ['id']
    204 
    205     search_list = []
    206     def get_search_list(self):
    207         return self.search_list
    208 
    209     search_group = []
    210     def get_search_group(self):
    211         return self.search_group
    212 
    213     def get_search_group_condition(self,request):
    214         condition = {}
    215         for option_object in self.get_search_group():
    216             if option_object.is_multi:
    217                 value_list = request.GET.getlist(option_object.field) #tags=[1,2]
    218                 if not value_list:
    219                     continue
    220                 condition['%s__in' %option_object.field] = value_list
    221             else:
    222                 value = request.GET.get(option_object.field)
    223                 if not value:
    224                     continue
    225                 condition[option_object.field] = value
    226 
    227         return condition
    228 
    229     def multi_delete(self,request):
    230         """
    231         批量删除
    232         :param request:
    233         :return:
    234         """
    235         pk_list = request.POST.getlist('pk')
    236         self.model_class.objects.filter(id__in=pk_list).delete()
    237 
    238     multi_delete.text = '一键删除'
    239 
    240     list_template = None
    241     def list_view(self,request,*args,**kwargs):
    242 
    243         ###################### 处理action #####################
    244 
    245         action_list = self.action_list
    246         action_dict = {func.__name__:func.text for func in action_list}
    247 
    248         if request.method == 'POST':
    249             func_name = request.POST.get('action')
    250             if func_name and func_name in action_dict:  #逻辑优化,防止被 方法乱入
    251                 func = getattr(self,func_name)
    252                 func(request)
    253 
    254 
    255         ###################### 1.搜索(有值才会显示搜索框) #####################
    256         search_list = self.get_search_list()
    257         search_value = request.GET.get('q','')
    258 
    259         from django.db.models import Q
    260         conn = Q()
    261         conn.connector = 'OR'
    262 
    263         if search_value:
    264             #Q,用于构造复杂的ORM查询条件
    265             for item in search_list:
    266                 conn.children.append((item,search_value))
    267 
    268         ######################### 2.获取排序 ###############################
    269         order_list = self.get_order_list()
    270 
    271         #组合搜索条件字典
    272         search_dict = self.get_search_group_condition(request)
    273 
    274         #自定义方法筛选后的结果
    275         queryset = self.get_queryset(**kwargs)
    276         # print(queryset)
    277         queryset = queryset.filter(conn).filter(**search_dict).all().order_by(*order_list)
    278 
    279         ###################### 3.处理分页(使用组件) #######################
    280         all_count = queryset.count()
    281         query_params = request.GET.copy() # ?=page=1&name='李四'
    282         query_params._mutable = True  #query_params['page']默认是不可以修改的
    283 
    284         pager = Pagination(
    285             current_page=request.GET.get('page'),
    286             all_count=all_count,
    287             base_url=request.path_info,
    288             query_params=query_params,
    289             per_page=self.per_page_count,
    290         )
    291 
    292         ###################### 4.处理表格 ##############################
    293         list_display = self.get_list_display()
    294         # 4.1处理表头
    295         header_list = []
    296         if list_display:
    297             for multi_key in list_display:
    298                 if isinstance(multi_key,FunctionType):  #判断 传入值是否为函数
    299                     verbose_name = multi_key(self,obj=None,is_header=True)
    300                 else:
    301                     verbose_name = self.model_class._meta.get_field(multi_key).verbose_name
    302                 header_list.append(verbose_name)
    303         else:
    304             header_list.append(self.model_class._meta.model_name)
    305 
    306         # 4.2处理表的内容
    307         data_list = queryset[pager.start:pager.end]
    308 
    309         body_list = []
    310         for row in data_list:  #row 是UserInfo object (1)
    311             row_list = []
    312 
    313             if list_display:
    314                 for multi_key in list_display:
    315                     if isinstance(multi_key,FunctionType):
    316                         row_list.append(multi_key(self,row,is_header=False,*args,**kwargs))
    317                     else:
    318                         row_list.append(getattr(row,multi_key))  #获取UserInfo object (1)的属性
    319             else:
    320                 row_list.append(row)
    321 
    322             body_list.append(row_list)
    323 
    324         ###################### 5.处理添加按钮 ##############################
    325         add_btn = self.get_add_btn(**kwargs)  #是一个URL
    326 
    327         ###################### 6.处理组合搜索 ##############################
    328         search_group_row_list = []
    329         search_group = self.get_search_group() # ['gender', 'depart']
    330         for keyword_object in search_group:  #keyword是一个Option类实例对象
    331             row = keyword_object.get_queryset_or_tuple(self.model_class,request,*args,**kwargs)
    332             #返回的是一个SearchGroupRow对象,且可迭代
    333             search_group_row_list.append(row)
    334 
    335 
    336         return render(request,
    337                       self.list_template or 'list.html',
    338                       {'body_list':body_list,
    339                        'header_list':header_list,
    340                        'pager':pager,
    341                        'add_btn':add_btn,
    342                        'search_list':search_list,
    343                        'search_value':search_value,
    344                        'action_dict':action_dict,
    345                        'search_group_row_list':search_group_row_list})
    346 
    347     def add_view(self,request,*args,**kwargs):
    348         """
    349         添加视图
    350         :param request:
    351         :return:
    352         """ 
    353 
    354         model_form = self.get_model_form()
    355         if request.method == 'GET':
    356             form = model_form
    357             return render(request, 'change.html', {'form': form})
    358 
    359         form = model_form(data=request.POST)
    360         if form.is_valid():
    361             response =  self.save(request,form,False,*args,**kwargs)
    362             return response or redirect(self.reverse_list_url(**kwargs))
    363         return render(request,'change.html',{'form':form})
    364 
    365     def get_change_object(self, request, pk, *args, **kwargs):
    366         return self.model_class.objects.filter(pk=pk).first()
    367 
    368     def change_view(self,request,pk,*args,**kwargs):
    369         """
    370         编辑视图
    371         :param request:
    372         :param pk:
    373         :return:
    374         """
    375         checked_obj = self.get_change_object(request, pk, *args, **kwargs)
    376 
    377         if not checked_obj:
    378             return render(request,'rbacerror.html')
    379 
    380         model_form = self.get_model_form()
    381         if request.method == 'GET':
    382             form = model_form(instance=checked_obj)
    383             return render(request, 'change.html', {'form': form})
    384 
    385         form = model_form(data=request.POST,instance=checked_obj)
    386         if form.is_valid():
    387             response = self.save(request, form, True, *args, **kwargs)
    388             return response or redirect(self.reverse_list_url(**kwargs))
    389         return render(request, 'change.html', {'form': form})
    390 
    391     def delete_object(self, request, pk, *args, **kwargs):
    392         self.model_class.objects.filter(pk=pk).delete()
    393 
    394     def delete_view(self,request,pk,*args,**kwargs):
    395         """
    396         删除视图
    397         :param request:
    398         :param pk:
    399         :return:
    400         """
    401         checked_obj  = self.model_class.objects.filter(pk=pk).first()
    402         if not checked_obj:
    403             return render(request,'rbacerror.html',)
    404 
    405         list_url = self.reverse_list_url(**kwargs)
    406         if request.method == 'GET':
    407             return render(request,'delete.html',{'list_url':list_url})
    408 
    409         response = self.delete_object(request, pk, *args, **kwargs)
    410         return response or redirect(list_url)
    411 
    412     def save(self,request,form,is_update,*args,**kwargs):
    413         form.save()
    414 
    415     def get_model_form(self):
    416         if self.model_form:
    417             return self.model_form
    418 
    419         class DynamicModelForm(forms.ModelForm):
    420             class Meta:
    421                 model = self.model_class
    422                 fields = "__all__"
    423 
    424             def __init__(self, *args, **kwargs):
    425                 super(DynamicModelForm, self).__init__(*args, **kwargs)
    426                 # 统一给ModelForm生成字段添加样式
    427                 for name, field in self.fields.items():
    428                     field.widget.attrs['class'] = 'form-control'
    429 
    430         return DynamicModelForm
    431 
    432     def display_edit(self,obj=None,is_header=None):
    433         """
    434         生成<编辑>a标签
    435         :param obj:
    436         :param is_header:
    437         :return:
    438         """
    439         if is_header:
    440             return "编辑操作"
    441         change_url = self.reverse_change_url(pk=obj.pk)
    442         return mark_safe('<a href="%s">编辑</a>'%change_url)
    443 
    444     def display_delete(self,obj=None,is_header=None):
    445         """
    446         生成<删除>a标签
    447         :param obj:
    448         :param is_header:
    449         :return:
    450         """
    451         if is_header:
    452             return "删除操作"
    453         delete_url = self.reverse_delete_url(pk=obj.pk)
    454         return mark_safe('<a href="%s">删除</a>'% delete_url)
    455 
    456     def display_checkbox(self,obj=None,is_header=None):
    457         """
    458         生成checkbox 批量操作
    459         :param obj:
    460         :param is_header:
    461         :return:
    462         """
    463         if is_header:
    464             return "选择"
    465         return mark_safe('<input type="checkbox" name="pk" value="%s">'%obj.pk)
    466 
    467 
    468     #视图函数放在这里是因为可以以后重写或者扩展(继承该类即可)!
    469     def get_urls(self):
    470         """
    471         生成视图函数
    472         :return:
    473         """
    474         patterns = [
    475             url(r'^list/$', self.wapper(self.list_view), name=self.get_list_url_name),
    476             url(r'^add/$', self.wapper(self.add_view), name=self.get_add_url_name),
    477             url(r'^change/(?P<pk>d+)/$', self.wapper(self.change_view), name=self.get_change_url_name),
    478             url(r'^delete/(?P<pk>d+)/$', self.wapper(self.delete_view), name=self.get_delete_url_name),
    479         ]
    480 
    481         patterns.extend(self.extra_urls())
    482         return patterns
    483 
    484     def extra_urls(self):
    485         return []
    486 
    487     def get_url_name(self,param):
    488         """
    489         返回别名(所有别名最后在这里处理)
    490         :param param:
    491         :return:
    492         """
    493         app_name = self.model_class._meta.app_label
    494         model_name = self.model_class._meta.model_name
    495         if self.prev:
    496             return '%s_%s_%s_%s' %(app_name,model_name,self.prev,param) #Web_customer_public_list
    497         return '%s_%s_%s' %(app_name,model_name,param)
    498 
    499     ######################### 生成带搜索条件的URL ########################
    500     def reverse_add_url(self,**kwargs):
    501         name = "%s:%s" % (self.site.namespace, self.get_add_url_name)  #stark:Web_customer_public_list
    502         url = reverse(name,kwargs=kwargs)
    503 
    504         if not self.request.GET:
    505             add_url = url
    506         else:
    507             param = self.request.GET.urlencode()  # page=1
    508 
    509             new_query_dict = QueryDict(mutable=True)
    510             new_query_dict['_filter'] = param  # <QueryDict: {'_filter': ['page=1']}>
    511 
    512             add_url = "%s?%s" % (url, new_query_dict.urlencode(()))
    513 
    514         return add_url
    515 
    516     def reverse_list_url(self,**kwargs):
    517         name = "%s:%s" % (self.site.namespace, self.get_list_url_name)
    518         url = reverse(name,kwargs=kwargs)
    519         if not self.request.GET:
    520             list_url = url
    521         else:
    522             param = self.request.GET.get('_filter')
    523             # print(param)  #page=1
    524             if not param:
    525                 return redirect(url)
    526             list_url = "%s?%s" % (url, param)
    527 
    528         return list_url
    529 
    530     def reverse_change_url(self,*args,**kwargs):
    531         name = "%s:%s" % (self.site.namespace, self.get_change_url_name)
    532         url = reverse(name,args=(*args,),kwargs=kwargs)
    533         if not self.request.GET:
    534             change_url = url
    535         else:
    536             param = self.request.GET.urlencode()  # page=1
    537 
    538             new_query_dict = QueryDict(mutable=True)
    539             new_query_dict['_filter'] = param  # <QueryDict: {'_filter': ['page=1']}>
    540 
    541             change_url = "%s?%s" % (url, new_query_dict.urlencode(()))
    542         return change_url
    543 
    544     def reverse_delete_url(self,*args,**kwargs):
    545         name = "%s:%s" % (self.site.namespace, self.get_delete_url_name)
    546         url = reverse(name,args=(*args,),kwargs=kwargs)
    547         if not self.request.GET:
    548             delete_url = url
    549         else:
    550             param = self.request.GET.urlencode()  # page=1
    551 
    552             new_query_dict = QueryDict(mutable=True)
    553             new_query_dict['_filter'] = param  # <QueryDict: {'_filter': ['page=1']}>
    554 
    555             delete_url = "%s?%s" % (url, new_query_dict.urlencode(()))
    556 
    557         return delete_url
    558 
    559     def reverse_commons_url(self,name,*args,**kwargs):
    560         """
    561         反向生成有别名的URL
    562         :param name: 别名
    563         :param args:
    564         :param kwargs:
    565         :return:
    566         """
    567         name = "%s:%s" % (self.site.namespace, name)
    568 
    569         url = reverse(name,args=(*args,),kwargs=kwargs )
    570 
    571         if not self.request.GET:
    572             commons_url = url
    573         else:
    574             param = self.request.GET.urlencode()  # page=1
    575 
    576             new_query_dict = QueryDict(mutable=True)
    577             new_query_dict['_filter'] = param  # <QueryDict: {'_filter': ['page=1']}>
    578 
    579             commons_url = "%s?%s" % (url, new_query_dict.urlencode(()))
    580 
    581         return commons_url
    582     ###################################################################
    583 
    584     def wapper(self,func):
    585         @functools.wraps(func)
    586         def inner(request,*args,**kwargs):
    587             self.request = request
    588             return func(request,*args,**kwargs)
    589         return inner
    590 
    591     @property
    592     def get_list_url_name(self):
    593         """
    594         获取列表页面URL的name
    595         :return:
    596         """
    597         return self.get_url_name('list')
    598 
    599     @property
    600     def get_add_url_name(self):
    601         """
    602         获取列表页面URL的name
    603         :return:
    604         """
    605         return self.get_url_name('add')
    606 
    607     @property
    608     def get_change_url_name(self):
    609         """
    610         获取列表页面URL的name
    611         :return:
    612         """
    613         return self.get_url_name('change')
    614 
    615     @property
    616     def get_delete_url_name(self):
    617         """
    618         获取列表页面URL的name
    619         :return:
    620         """
    621         return self.get_url_name('delete')
    622 
    623 
    624 class StarkSite(object):
    625     def __init__(self):
    626         self._registry = []
    627         self.app_name = 'stark'
    628         self.namespace = 'stark'
    629 
    630     def register(self, model_class, handler_class=None,prev=None):
    631         """
    632 
    633         :param model_class:models中的数据库相关的类(是一个类!!)
    634         :param handler_class:处理请求的视图函数所在的类
    635         :param prev:url前缀
    636         :return:
    637         """
    638         print('hello,zifeng')
    639         """
    640         [
    641             {"model_class":models.Userinfo,'handler':UserinfoHanler(model.Userinfo)}
    642         ]
    643         
    644         [
    645         {'model_class': <class 'app01.models.UserInfo'>, 这是类!
    646         'handler': <app01.stark.UserinfoHandler object at 0x00000293A125A8D0>  这是对象!}
    647         ]
    648         """
    649         if not handler_class:
    650             handler_class = StarkHandler
    651         self._registry.append({'prev':prev,'model_class':model_class,'handler':handler_class(self,model_class,prev)})
    652 
    653 
    654     def get_urls(self):
    655         patterns = []
    656         for item in self._registry:
    657             prev = item['prev']
    658             model_class = item['model_class']
    659             handler = item['handler']
    660             app_name = model_class._meta.app_label
    661             model_name = model_class._meta.model_name
    662 
    663             if prev:
    664                 patterns.append(url(r'^%s/%s/%s/'%(app_name,model_name,prev),(handler.get_urls(),None,None)))
    665             else:
    666                 patterns.append(url(r'^%s/%s/' % (app_name, model_name), (handler.get_urls(), None,None)))
    667 
    668         # patterns.append()
    669         return patterns
    670 
    671     @property
    672     def urls(self):
    673         return self.get_urls(),self.app_name,self.namespace
    674 
    675 
    676 site = StarkSite()
    View Code

    apps.py

    1 from django.apps import AppConfig
    2 from django.utils.module_loading import autodiscover_modules
    3 
    4 class StarkConfig(AppConfig):
    5     name = 'stark'
    6 
    7     def ready(self):
    8         autodiscover_modules('stark')
    View Code
  • 相关阅读:
    Java并发容器总结
    ReentrantLock源码分析
    webpack插件之webpack-dev-server
    webpack插件之htmlWebpackPlugin
    webpack配置之webpack.config.js文件配置
    webpack的安装和运行
    webpack安装大于4.x版本(没有配置webpack.config.js)
    webpack安装低于4版本(没有配置webpack.config.js)
    什么是webpack以及为什么使用它
    webpack前置知识2(JavaScript项目初始化)
  • 原文地址:https://www.cnblogs.com/steven2020/p/10714427.html
Copyright © 2011-2022 走看看