stark组件
1. stark也是一个app(用startapp stark创建),目标时把这个做成一个可以拔插的组件 2. setting文件下INSTALLED_APPS 路径要配置好(app的注册) 3. 写好sites.py中的site类,实例化出一个类对象,其他文件都直接引用这个类对象(单例模式), 4. 模型类和数据库也要确定好
from django.urls import path,re_path from django.shortcuts import HttpResponse,render,redirect from django.utils.safestring import mark_safe from django.core.exceptions import FieldDoesNotExist from django.urls import reverse from django.db.models import Q class ShowList(object): def __init__(self,request,config_obj,queryset): #展示页面的自定制变量 self.config_obj=config_obj self.queryset=queryset self.request=request self.pager_queryset=self.get_pager_queryset() #分页 def get_pager_queryset(self): #分页功能 from stark.utils.page import Pagination #一般是在stark组件下新建一个文件夹写好功能后直接倒过来 current_page = self.request.GET.get("page", 1) self.pagination = Pagination(self.request, current_page, self.queryset, per_page_num=self.config_obj.per_page_num or 5) queryset = self.queryset[self.pagination.start:self.pagination.end] return queryset def get_header(self): ''' 获取表头 :return: ''' # 构建表头 header_list = [] for field_or_func in self.config_obj.get_new_list_display(): if callable(field_or_func): val = field_or_func(self.config_obj, header=True) header_list.append(val) # header_list.append(field_or_func.__name__) else: if field_or_func == "__str__": val = self.config_obj.model._meta.model_name.upper() print(val) else: field_obj = self.config_obj.model._meta.get_field(field_or_func) val = field_obj.verbose_name header_list.append(val) return header_list def get_body(self): ''' 获取标体 :return: ''' # 构建展示数据 new_data = [] for obj in self.pager_queryset: temp = [] for field_or_func in self.config_obj.get_new_list_display(): # ["title","price","state","publish",show_authors] if callable(field_or_func): # field:方法 val = field_or_func(self.config_obj, obj) else: try: # field:字符串 from django.db.models.fields.related import ManyToManyField field_obj = self.config_obj.model._meta.get_field(field_or_func) # 判断是否多对多字段 if type(field_obj) == ManyToManyField: raise Exception("list_display不能是多对多字段!") # 判断字段是否 拥有choices属性 if field_obj.choices: val = getattr(obj, "get_%s_display" % field_or_func)() else: val = getattr(obj, field_or_func) if field_or_func in self.config_obj.list_display_links: val = mark_safe("<a href='%s'>%s</a>" % (self.config_obj.get_change_url(obj), val)) except FieldDoesNotExist as e: # val=obj val = getattr(obj, field_or_func)() temp.append(val) new_data.append(temp) print("new_data", new_data) # [['python', Decimal('123.00')], ['java', Decimal('234.00')]] ''' 目标数据结构 new_data=[ ["python",123], ["java",234] ] ''' return new_data class ModelStark(object): ''' 默认配置类 ''' list_display=("__str__",) list_display_links = [] model_form_class=None per_page_num=None search_fields=[] search_val=None list_filter=[] list_title=None def __init__(self,model): self.model=model self.model_name = self.model._meta.model_name self.app_label = self.model._meta.app_label # 反向解析当前访问表的增删改查URL def get_list_url(self): # 反向解析当前表的删除的URL list_url = reverse("%s_%s_list" % (self.app_label, self.model_name)) return list_url def get_add_url(self): # 反向解析当前表的删除的URL add_url = reverse("%s_%s_add" % (self.app_label, self.model_name)) return add_url def get_delete_url(self,obj): # 反向解析当前表的删除的URL delete_url = reverse("%s_%s_delete" % (self.app_label, self.model_name), args=(obj.pk,)) return delete_url def get_change_url(self, obj): # 反向解析当前表的删除的URL change_url = reverse("%s_%s_change" % (self.app_label, self.model_name), args=(obj.pk,)) return change_url # 三个默认列 def show_checkbox(self, obj=None, header=False): if header: return mark_safe("<input type='checkbox'>") return mark_safe("<input name='_selected_action' value=%s type='checkbox'>"%obj.pk) def show_delbtn(self, obj=None, header=False): if header: return "删除" return mark_safe("<a href='%s'>删除</a>"%self.get_delete_url(obj)) def show_editbtn(self, obj=None, header=False): if header: return "编辑" return mark_safe("<a href='%s'>编辑</a>" %self.get_change_url(obj)) # 构建新的list_display def get_new_list_display(self): temp=[] temp.extend(self.list_display) temp.append(ModelStark.show_editbtn) temp.append(ModelStark.show_delbtn) temp.insert(0,ModelStark.show_checkbox) return temp def get_search_condition(self,request): val = request.GET.get("q") q = Q() if val: self.search_val = val q.connector = "or" for field in self.search_fields: # ["title","price"] print(field) # queryset=queryset.filter(Q(title__contains=val)|Q(price__contains=val)) q.children.append((field + "__contains", val)) else: self.search_val=None return q # action参数 def patch_delete(self,request,queryset): # [1,3] queryset.delete() patch_delete.desc="批量删除" actions=[] def get_new_actions(self): temp=[] temp.extend(self.actions) temp.append(self.patch_delete) return temp def get_action_dict(self): actions_list=[] for func in self.get_new_actions(): actions_list.append({ "name":func.__name__, "desc":func.desc, }) return actions_list # [{"name":"patch_delete","desc":"批量删除"}] def get_list_filter_links(self): list_filter_links={} print(self.list_filter) # ["publish","authors","state"] for filter_field in self.list_filter: import copy params = copy.deepcopy(self.request.GET) # {"publish":1,"authors":1} current_field_val=params.get(filter_field) filter_field_obj=self.model._meta.get_field(filter_field) print(">>>",type(filter_field_obj)) from django.db.models.fields.related import ForeignKey,ManyToManyField # 针对一对多或者多对多过滤字段 if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField): # print("____>",filter_field_obj.remote_field.model) # <class 'app01.models.Publish'> # data=filter_field_obj.remote_field.model.objects.all() # print(data) rel_model = filter_field_obj.remote_field.model _limit_choices_to = filter_field_obj.remote_field.limit_choices_to data = rel_model.objects.filter(**_limit_choices_to) elif filter_field_obj.choices: # 针对choice字段类型 data=filter_field_obj.choices # [(1,"已出版"),(2,"未出版社")] else: raise Exception("过滤字段不能太普通!") # 为每一个数据构建成一个a标签 temp = [] # params2=copy.deepcopy(params) if params.get(filter_field): del params[filter_field] all = "<a class='btn btn-default btn-sm' href='?%s'>全部</a>"%params.urlencode() temp.append(all) for item in data: if type(item)==tuple: # 元组类型 pk,text = item else: # model对象类型 pk,text = item.pk,str(item) params[filter_field]=pk # *********** _url="?%s"%(params.urlencode()) # *********** if current_field_val==str(pk): link="<a class='active btn btn-default btn-sm' href='%s'>%s</a>"%(_url,text) else: link = "<a class='btn btn-default btn-sm' href='%s'>%s</a>" % (_url, text) temp.append(link) list_filter_links[filter_field]=temp return list_filter_links def get_list_filter_condition(self): q=Q() for filter_field,val in self.request.GET.items(): if filter_field in ["page","q"]:continue q.children.append((filter_field,val)) return q # 视图函数 def list_view(self,request,querySet=None,flag=False): ''' self: 当前访问模型表对应的配置类对象 self.model: 当前访问模型表 :param request: :return: ''' self.request=request if request.method=="POST": # action操作 action_func_str=request.POST.get("action") if action_func_str: action_func=getattr(self,action_func_str) _selected_action=request.POST.getlist("_selected_action") # [1,3] queryset=self.model.objects.filter(pk__in=_selected_action) action_func(request,queryset) if not flag: # print("self.model.__class__",self.__class__.__dict__) self.list_filter=self.__class__.__dict__.get("list_filter",[]) self.actions=self.__class__.__dict__.get("actions",[]) self.list_title=self.__class__.__dict__.get("list_title",[]) if flag: queryset=querySet else: queryset=self.model.objects.all() # search过滤 search_condition=self.get_search_condition(request) # list_filter多级过滤 list_filter_condition=self.get_list_filter_condition() queryset=queryset.filter(search_condition).filter(list_filter_condition) show_list=ShowList(request,self,queryset) # 相关变量 table_name=self.model._meta.verbose_name add_url=self.get_add_url() # # 获取登录人权限 # print("Per:",request.session.get("permission_list")) # permission_list=request.session.get("permission_list") # menu_permissions=[] # for permission in permission_list: # if permission.get("type")=="button":continue # menu_permissions.append(permission) import datetime now=datetime.datetime.now() title=self.list_title or "查看数据" return render(request,'stark/list_view.html',locals()) def get_model_form(self): from django.forms import ModelForm class BaseModelForm(ModelForm): class Meta: model = self.model fields = "__all__" return self.model_form_class or BaseModelForm def add_view(self,request): BaseModelForm=self.get_model_form() if request.method=="GET": form_obj=BaseModelForm() print(form_obj) return render(request,"stark/add_view.html",locals()) else: form_obj = BaseModelForm(request.POST) if form_obj.is_valid(): form_obj.save() return redirect(self.get_list_url()) else: return render(request, "stark/add_view.html", locals()) def change_view(self,request,id): BaseModelForm=self.get_model_form() edit_obj=self.model.objects.filter(pk=id).first() if request.method=="GET": form_obj=BaseModelForm(instance=edit_obj) return render(request,"stark/change_view.html",locals()) else: form_obj = BaseModelForm(request.POST,instance=edit_obj) if form_obj.is_valid(): form_obj.save() return redirect(self.get_list_url()) else: return render(request, "stark/change_view.html", locals()) def delete_view(self,request, id): if request.method=="POST": self.model.objects.filter(pk=id).delete() return redirect(self.get_list_url()) list_url=self.get_list_url() return render(request,"stark/delete_view.html",locals()) def get_extra_url(self): return [] @property def get_urls(self): temp = [ path("", self.list_view,name="%s_%s_list"%(self.app_label,self.model_name)), path("add/", self.add_view,name="%s_%s_add"%(self.app_label,self.model_name)), re_path("(\d+)/change/", self.change_view,name="%s_%s_change"%(self.app_label,self.model_name)), re_path("(\d+)/delete/", self.delete_view,name="%s_%s_delete"%(self.app_label,self.model_name)), ] temp.extend(self.get_extra_url()) return (temp, None, None) class StarkSite: ''' stark全局类 ''' def __init__(self): self._registry = {} def register(self, model, admin_class=None, **options): admin_class = admin_class or ModelStark self._registry[model] = admin_class(model) def get_urls(self): # 动态为注册的模型类创建增删改查URL temp = [] # {Book:ModelAdmin(Book),Publish:ModelAdmin(Publish)} for model, config_obj in self._registry.items(): print("---->", model, config_obj) model_name = model._meta.model_name app_label = model._meta.app_label temp.append( path("%s/%s/" % (app_label,model_name),config_obj.get_urls) ) ''' path("stark/app01/book",BookConfig(Book).list_view) path("stark/app01/book/add",BookConfig(Book).add_view) path("stark/app01/publish",ModelAdmin(Publish).list_view) path("stark/app01/publish/add",ModelAdmin(Publish).add_view) ''' return temp @property def urls(self): return self.get_urls(),None,None site = StarkSite()
来源:https://www.cnblogs.com/yang950718/p/10770937.html