• 类Xadmin插件--海豚插件


    一款类似于xadmin的仿制Django内部admin管理的插件。用于系统开发。起个好听的名字。海豚插件。

    from django.contrib import admin
    from Dolphin.service.Dolphin import site,ModelDolphin
    from django.shortcuts import HttpResponse,render,redirect,reverse
    from django.utils.safestring import mark_safe
    from ocas.models import *
    from django.forms import ModelForm
    # Register your models here.
    
    class CompanyConfig(ModelDolphin):
    
        # def xxx(self,obj=None,header=False):
        #     if header:
        #         return "显示标题(可修改)"
        #     return 123
    
        list_display=('id','full_name','short_name','registered_capital',
                        'quality_management_system_certificate',"occupational_health_and_safety_system_certificate",
                        'environmental_management_system_certificate','staff_headcount','staff_productor_count','staff_main_network_engineer_count',
                      'b_city','qualifications'
                      )
        list_display_links = ("full_name",)
        search_fields = ('full_name',)
        list_per_page=5
        # def patch_init(self,request,queryset):
        #     print(queryset)
        # patch_init.short_description = "批量初始化"
        # actions = (patch_init,)
    
        list_filter = ('b_city','qualifications','using_software',)#
    
    class StaffModelForm(ModelForm):
        class Meta:
            model=Staff
            fields="__all__"
            exclude=('is_delete',)
    
    
    class StaffConfig(ModelDolphin):
        list_display = ('id','sjdw','user','gender','native_place',)
        modelform_class = StaffModelForm
        search_fields = ('user',)
        list_filter = ('sjdw',)
    
    class SoftwareConfig(ModelDolphin):
        # list_display = ('id',)
        list_per_page = 5
    
    site.register(Company,CompanyConfig)
    site.register(Qualification)
    site.register(Software,SoftwareConfig)
    site.register(Vendor)
    site.register(City)
    site.register(Staff,StaffConfig)
    site.register(UserInfo,)
    # print(site._registry)
    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    '''
    Administrator 
    2019/2/20 
    '''
    from django.urls import include, path, re_path
    from django.conf.urls import url
    from django.shortcuts import HttpResponse,render,redirect,reverse
    from django.utils.safestring import mark_safe
    from collections import deque
    from django.forms import ModelForm
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    import copy
    from django.db.models import Q
    from django.db.models.fields.related import ManyToManyField,ForeignKey
    from django.forms.models import ModelMultipleChoiceField,ModelChoiceField
    from django.forms.fields import BooleanField
    # from Dolphin.service.dolform import ModelFormDemo
    class ShowList(object):
        def __init__(self,config,data_list,request):
            self.config=config
            self.data_list=data_list
            self.request=request
            self.page_data=self.get_query_sets()
            #action
            self.actions=self.config.new_actions
        def get_action_list(self):
            temp=[]
            # print(self.actions)
            for func_obj in self.actions:
                temp.append({
                    "name":func_obj.__name__,
                    # "desc":func_obj.short_description
                    # "desc":getattr(func_obj,"short_description",func_obj.__name__)
                    "desc":func_obj.short_description if hasattr(func_obj, "short_description") else func_obj.__name__
                })
            return temp
        def get_header(self):
            # 构建表头数据
            header_list = []
            for filed in self.config.new_list_play():
                if callable(filed):
                    # header_list.append(filed.__name__.upper())
                    header_list.append(filed(self.config, header=True))
                elif filed == "__str__":
                    header_list.append(self.config.model._meta.model_name.upper())
                else:
                    header_list.append(self.config.model._meta.get_field(filed).verbose_name)
                    # header_list.append(filed[:10].upper
            return header_list
        def get_body(self):
            new_data_list = []
    
            for obj in self.page_data:
                temp = []
                for field in self.config.new_list_play():
                    if callable(field):
                        val = field(self.config, obj)
                    else:
                        try:
                            field_obj=self.config.model._meta.get_field(field)
                            if isinstance(field_obj,ManyToManyField):
                                ret = getattr(obj, field).all()
                                t = []
                                for m2m_obj in ret:
                                    t.append('''<span class='label label-primary'>{0}</span>'''.format(m2m_obj))
                                val=mark_safe('<br>'.join(t))
                            else:
                                val = getattr(obj, field)
                                if field in self.config.list_display_links:
                                    _url = self.config.reverse_url("change", obj)
                                    val = mark_safe("<a href={0}>{1}</a>".format(_url, val))
                        except Exception as e:
                            val = getattr(obj, field)
                            # if field in self.config.list_display_links:
                            #     _url = self.config.reverse_url("change", obj)
                            #     val = mark_safe("<a href={0}>{1}</a>".format(_url, val))
    
                    temp.append(val)
                new_data_list.append(temp)
            return new_data_list
        def get_query_sets(self):
            paginator = Paginator(self.data_list, self.config.list_per_page)
            page = self.request.GET.get('page')
            try:
                query_sets = paginator.page(page)
            except PageNotAnInteger:
                query_sets = paginator.page(1)
            except EmptyPage:
                query_sets = paginator.page(paginator.num_pages)  # Paginator.num_pages:总共分页数
            return query_sets
        def new_pagination(self):
            params = copy.deepcopy(self.request.GET)  # {"page":"12","title_startwith":"py","id__gt":"5"}
            url_prefix = self.request.path#当前路径
            page_html=""
            added_dot_ele = False
            for page_num in self.page_data.paginator.page_range:
                params["page"] = page_num
                if page_num<3 or page_num>self.page_data.paginator.num_pages-2 
                    or abs(self.page_data.number-page_num)<=2:#代表前面两页和后面两页
                    ele_class=""
                    if self.page_data.number==page_num:
                        added_dot_ele=False
                        ele_class="active"
                    page_html+='''<li class="{0}"><a href="{1}?{2}">{3}</a></li>'''.format(ele_class,url_prefix,params.urlencode(),page_num)
                else:
                    if not added_dot_ele:
                        page_html += '<li><a>...</a></li>'
                        added_dot_ele = True
    
            if self.page_data.has_previous():
                params["page"] = self.page_data.previous_page_number()
                page_html='''<li><a href="{0}?{1}">«</a></li>'''.format(url_prefix,params.urlencode())+page_html
            else:
                page_html='''<li class="disabled" ><a href="javascript:void(0);">«</a></li>'''+page_html
    
            if self.page_data.has_next():
                params["page"] =self.page_data.next_page_number()
                page_html+='''<li><a href="{0}?{1}">»</a></li>'''.format(url_prefix,params.urlencode())
            else:
                page_html+='''<li class="disabled" ><a href="javascript:void(0);">»</a></li>'''
            return page_html
        def get_filter_linktags(self):
            link_list={}
            url_prefix = self.request.path  # 当前路径
            for filter_field in self.config.list_filter:
                params = copy.deepcopy(self.request.GET)
                cid=self.request.GET.get(filter_field,0)
                filter_field_obj=self.config.model._meta.get_field(filter_field)
                filter_field_verbose_name="以 {0}".format(filter_field_obj.verbose_name)
                if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
    
                    # data_list=filter_field_obj.rel.to.objects.all()  #django 1.0的用法
                    data_list=filter_field_obj.related_model.objects.all()#django 2.0 的用法
                else:
                    data_list=self.config.model.objects.values("pk",filter_field)
                temp=[]
                #处理 全部标签
                if params.get(filter_field):
                    del params[filter_field]
                    active = ""
                else:
                    active = "active"
                temp.append('''<li class={0}><a href='{1}?{2}'>全部</a></li>'''.format(active,url_prefix,params.urlencode(),))
                for obj in data_list:
                    if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
                        pk=obj.pk
                        text=str(obj)
                        params[filter_field] = pk
                    else:
                        pk=obj.get("pk")
                        text=obj.get(filter_field)
                        params[filter_field] = text
                    if cid==str(pk) or cid==text:
                        active="active"
                    else:
                        active=""
                        # params[filter_field]=pk
                    a_ele = '''<li class={0}><a href='{1}?{2}'>{3}</a></li>'''.format(active,url_prefix,params.urlencode(),text)
                    temp.append(a_ele)
                #
                link_list[filter_field_verbose_name]=temp
            return link_list
    
    class ModelDolphin(object):
    
        list_display = ('__str__',)
        list_display_links = ()
        list_per_page=10#默认每页展示10行数据
        search_fields=()#关键词搜索
        actions=()#自定义字段
        list_filter=()#分组查询
        #用户可以自定义ModelForm
        modelform_class=None
    
        def __init__(self,model,site):
            self.model=model
            self.site=site
        def reverse_url(self,string,obj=None):
            app_label = self.model._meta.app_label
            model_name = self.model._meta.model_name
            if string in ["change","delete",]:
                _url = reverse("{app_label}_{model_name}_{action}".format(app_label=app_label, model_name=model_name,
                                                                          action=string),
                               args=(obj.pk,))
                return _url
            elif string in ["add","list"]:
                _url = reverse("{app_label}_{model_name}_{action}".format(app_label=app_label, model_name=model_name,
                                                                          action=string),)
                return _url
            else:
                raise AttributeError("参数有误,没有这个属性.只能使用 change/delete/add/list")
        def edit(self,obj=None,header=False):
            if header:
                return "编辑"
            app_label = self.model._meta.app_label
            model_name = self.model._meta.model_name
            # _url =reverse( "{app_label}_{model_name}_change".format(app_label=app_label, model_name=model_name),args=(obj.pk,))
            _url=self.reverse_url("change",obj)
            # return mark_safe("<a href='{0}/change'>编辑</a>".format(obj.pk))
            return mark_safe("<a href='{_url}'>编辑</a>".format(_url=_url,pk=obj.pk))
    
        def deletes(self,obj=None,header=False):
            if header:
                return "删除"
            # app_label = self.model._meta.app_label
            # model_name = self.model._meta.model_name
            # _url = reverse("{app_label}_{model_name}_delete".format(app_label=app_label, model_name=model_name),
            #                args=(obj.pk,))
            _url=self.reverse_url("delete",obj)
            return mark_safe('''<a href='{_url}'>删除</a>'''.format(_url=_url))
        def checkbox(self,obj=None,header=False):
            if header:
                return mark_safe("<input id='choice' type='checkbox'/>")
            return mark_safe("<input class='choice_item' type='checkbox' name='selected_pk' value='{val}'/>".format(val=obj.pk))
    
        def new_list_play(self):
            temp=[]
            temp.append(ModelDolphin.checkbox)
            temp.extend(self.list_display)
            if not self.list_display_links:
                temp.append(ModelDolphin.edit)
            temp.append(ModelDolphin.deletes)
            return temp
        def display_all_related_objs(self,objs):
            #objs=[objs,]
            ul_ele="<ul>"
            for obj in objs:
                li_ele='''<li>{0}:{1}</li>'''.format(obj._meta.verbose_name,obj.__str__().strip("<>"))
                ul_ele+=li_ele
                for m2m_field in obj._meta.local_many_to_many:
                    sub_ul_ele="<ul>"
                    m2m_field_obj=getattr(obj,m2m_field.name)
                    for o in m2m_field_obj.select_related():
                        li_ele = '''<li>{0}:{1}</li>'''.format(m2m_field.verbose_name, o.__str__().strip("<>"))
                        sub_ul_ele+=li_ele
                    sub_ul_ele+="</ul>"
                    ul_ele+=sub_ul_ele
                for related_obj in obj._meta.related_objects:
                    if 'ManyToManyRel' in related_obj.__repr__():
    
                        if hasattr(obj, related_obj.get_accessor_name()):  # hassattr(customer,'enrollment_set')
                            accessor_obj = getattr(obj, related_obj.get_accessor_name())
                            # print("-------ManyToManyRel", accessor_obj, related_obj.get_accessor_name())
                            # 上面accessor_obj 相当于 customer.enrollment_set
                            if hasattr(accessor_obj, 'select_related'):  # slect_related() == all()
                                target_objs = accessor_obj.select_related()  # .filter(**filter_coditions)
                                # target_objs 相当于 customer.enrollment_set.all()
    
                                sub_ul_ele = "<ul style='color:red'>"
                                for o in target_objs:
                                    li_ele = '''<li> %s: %s </li>''' % (o._meta.verbose_name, o.__str__().strip("<>"))
                                    sub_ul_ele += li_ele
                                sub_ul_ele += "</ul>"
                                ul_ele += sub_ul_ele
    
                    elif hasattr(obj, related_obj.get_accessor_name()):  # hassattr(customer,'enrollment_set')
                        accessor_obj = getattr(obj, related_obj.get_accessor_name())
                        # 上面accessor_obj 相当于 customer.enrollment_set
                        if hasattr(accessor_obj, 'select_related'):  # slect_related() == all()
                            target_objs = accessor_obj.select_related()  # .filter(**filter_coditions)
                            # target_objs 相当于 customer.enrollment_set.all()
                        else:
                            print("one to one i guess:", accessor_obj)
                            target_objs = accessor_obj
    
                        if len(target_objs) > 0:
                            # print("33[31;1mdeeper layer lookup -------33[0m")
                            # nodes = recursive_related_objs_lookup(target_objs,model_name)
    
                            nodes = self.display_all_related_objs(target_objs)
                            ul_ele += nodes
            ul_ele += "</ul>"
            return ul_ele
    
        def batch_remove(self,request,queryset):
            queryset.delete()
            # relected_obj=self.display_all_related_objs(queryset)
            # # print(html_str)
            # return render(request,'dolphin/dol_delete.html',locals())
        batch_remove.short_description = "批量删除"
        @property
        def new_actions(self):
            temp=[]
            temp.append(ModelDolphin.batch_remove)
            temp.extend(self.actions)
            return temp
        def set_pop_tags(self,forms):
            for bfield in forms:
                if isinstance(bfield.field,ModelMultipleChoiceField) or isinstance(bfield.field,ModelChoiceField):
                    bfield.is_pop=True
                    #两种方式获取类  一对多 或者多对多 的关联表  模型
                    # filter_field_obj = self.model._meta.get_field(bfield.name).related_model
                    filter_field_obj=bfield.field.queryset.model
                    # print("----",bfield.name,type(bfield.name),filter_field_obj)
                    # print("+++++++++",filter_field_obj2)
                    related_app_label = filter_field_obj._meta.app_label
                    related_model_name = filter_field_obj._meta.model_name
                    _url=reverse("{related_app_label}_{related_model_name}_add".format(related_app_label=related_app_label,
                                                                                       related_model_name=related_model_name))
                    bfield.url=_url+"?pop_res_id={0}".format(bfield.auto_id )
                # if isinstance(bfield.field,BooleanField):
                #     print(bfield)
                #     bfield.is_checkbox=True
            return forms
        def get_modelform_class(self):
            if not self.modelform_class:
                class ModelFormDemo(ModelForm):
                    class Meta:
                        model = self.model
                        fields = "__all__"
                        # exclude = ("is_delete",)
                return ModelFormDemo
            else:
                return self.modelform_class
        def get_search_condition(self,request):
            key_word = request.GET.get("key_words","")
            self.key_word=key_word
            # 获取当前列表中的所有数据
    
            search_connection = Q()
            search_connection.connector = "OR"
            for search_field in self.search_fields:
                search_connection.children.append(("{field}__contains".format(field=search_field), key_word))
            return search_connection
        def get_filter_condition(self,request):
            filter_condition = Q() #默认且
            for filter_field, val in request.GET.items():
                if filter_field in self.list_filter:
                    filter_condition.children.append((filter_field, val))
            return filter_condition
        def list_view(self, request):
            if request.method=="POST":
                action= request.POST.get("action")
                selected_pk=request.POST.getlist("selected_pk")
                warning_flag=False
                if hasattr(self,action) and selected_pk:
                    action_func=getattr(self,action)
                    queryset = self.model.objects.filter(pk__in=selected_pk)
                    action_func(request, queryset)
                else:
                    warning_flag=True
            search_condition=self.get_search_condition(request)#获取  第一次关键词筛选的条件get("selected_pk")
            filter_condition=self.get_filter_condition(request)#获取  第二次过滤的条件
            # data_list=self.model.objects.all().filter(search_connection)#第一次筛选后的所有数据  通过关键词查询
            data_list = self.model.objects.get_queryset().filter(search_condition).filter(filter_condition)  # 解决异常 UnorderedObjectListWarning
            showlist=ShowList(self,data_list,request)
            #拿到表名
            tablename=self.model._meta.verbose_name_plural
            #构建一个添加数据连接
            add_url=self.reverse_url("add")
    
            return render(request, "dol_list.html", locals())#可以是 locals()
    
        def add_view(self, request):
            ModelFormDemo=self.get_modelform_class()
            list_url=self.reverse_url('list')
            forms =self.set_pop_tags(ModelFormDemo())
    
    
            if request.method=="POST":
                forms=self.set_pop_tags(ModelFormDemo(request.POST))
    
                if forms.is_valid():
                    obj=forms.save()
                    pop_res_id=request.GET.get("pop_res_id",None)
                    if pop_res_id:
                        res={"pk":obj.pk,"text":str(obj),"pop_res_id":pop_res_id}
    
                        return render(request, "dol_pop.html", {"res":res})
                    else:
                        return redirect(list_url)
    
    
            return render(request, "dol_add.html", locals())
    
        def change_view(self, request, id):
    
            ModelFormDemo = self.get_modelform_class()
            edit_obj=self.model.objects.filter(pk=id).first()
            list_url = self.reverse_url('list')
            if request.method=="POST":
                forms=ModelFormDemo(request.POST,instance=edit_obj)
                if forms.is_valid():
                    forms.save()
                    return redirect(list_url)
                return render(request, "dol_change.html", locals())
            forms = ModelFormDemo(instance=edit_obj)
            return render(request, "dol_change.html", locals())
    
        def delete_view(self, request, id):
            url_list = self.reverse_url('list')
            delete_obj=self.model.objects.filter(pk=id)
            print("####",delete_obj)
    
            if request.method=="POST":
                delete_obj.delete()
                return redirect(url_list)
            delete_obj_detail=self.display_all_related_objs(delete_obj)
            return render(request, "dol_delete.html", locals())
    
        @property
        def get_urls2(self):
            app_label = self.model._meta.app_label
            model_name = self.model._meta.model_name
            temp = []
            # print("#"*20)
            temp.append(re_path(r'^$', self.list_view,name="{app_label}_{model_name}_list".format(app_label=app_label,model_name=model_name)))
            temp.append(re_path(r'^add/$', self.add_view,name="{app_label}_{model_name}_add".format(app_label=app_label,model_name=model_name)))
            temp.append(re_path(r'^(d+)/change/$', self.change_view,name="{app_label}_{model_name}_change".format(app_label=app_label,model_name=model_name)))
            temp.append(re_path(r'^(d+)/delete/$', self.delete_view,name="{app_label}_{model_name}_delete".format(app_label=app_label,model_name=model_name)))
    
            return temp
        @property
        def urls2(self):
            return self.get_urls2, None, None
    class DolphinSite(object):
        def __init__(self,name='admin'):
            self._registry={}
    
        def get_urls(self):
            temp=[]
            for model,dolphin_class_obj in self._registry.items():
                app_name=model._meta.app_label
                model_name=model._meta.model_name
                temp.append(path('{0}/{1}/'.format(app_name,model_name),dolphin_class_obj.urls2),)
            return temp
        @property
        def urls(self):
            return self.get_urls(),None,None
        def register(self, model, dolphin_class=None, **options):
            if not dolphin_class:
                dolphin_class=ModelDolphin
            self._registry[model] = dolphin_class(model, self)#放进字典里面
    
    site=DolphinSite()
    server.Dolphin.py
  • 相关阅读:
    记我安装Caffe的血泪史(1)
    UWP连接mysql 实现数据远程备份
    数据库性能测试
    性能瓶颈分析定位
    系统安全性测试
    WEB安全性测试点
    jmeter测试报告分析
    Linux常用命令大全
    软件测试入门到飞升上仙之客户端
    软件测试入门到飞升上仙之web 端测试
  • 原文地址:https://www.cnblogs.com/Mengchangxin/p/10468878.html
Copyright © 2020-2023  润新知