标签:djang mutable pes lse 组合 error 统一 pen label
Files
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,‘rbac\error.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,‘rbac\error.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()
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‘)
标签:djang mutable pes lse 组合 error 统一 pen label
原文地址:https://www.cnblogs.com/steven2020/p/10714427.html