django_models后台管理myarya
arya重点代码
# urls.py from django.urls import path,re_path,include from arya.service import v1 urlpatterns = [ re_path("^arya/",v1.site.urls), ] # arya/service/v1.py def get_urls(self): from django.conf.urls import url, include urlpatterns = [ url(r'^$', self.index, name='index'), url(r'^login/$', self.login, name='login'), url(r'^logout/$', self.logout, name='logout'), ] for model_class, arya_model_obj in self._registry.items(): urlpatterns += [ url(r'^%s/%s/' % (model_class._meta.app_label, model_class._meta.model_name), include(arya_model_obj.urls)) ] return urlpatterns @property def urls(self): """ 创建URL对应关系 :return: 元组类型:url关系列表或模块(模块内部必须有urlpatterns属性);app_name;namespace """ return self.get_urls(), self.app_name, self.namespace
# arya/service/v1.py def __init__(self, app_name='arya', namespace='arya'): self.app_name = app_name self.namespace = namespace self._registry = {} def register(self, model_class, arya_model_class=BaseAryaModal): self._registry[model_class] = arya_model_class(model_class, self) # app/arya.py class MovieAdmin(v1.BaseAryaModal): """""" v1.site.register(models.Movie,MovieAdmin)
# 对每一个models进行url细分,curd。 # site for model_class, arya_model_obj in self._registry.items(): urlpatterns += [ url(r'^%s/%s/' % (model_class._meta.app_label, model_class._meta.model_name), include(arya_model_obj.urls)) ] # BaseAryaModal def get_urls(self): from django.conf.urls import url info = self.model_class._meta.app_label, self.model_class._meta.model_name urlpatterns = [ url(r'^$', self.changelist_view, name='%s_%s_changelist' % info), url(r'^add/$', self.add_view, name='%s_%s_add' % info), url(r'^(.+)/delete/$', self.delete_view, name='%s_%s_delete' % info), url(r'^(.+)/change/$', self.change_view, name='%s_%s_change' % info), url(r'^(.+)/detail/$', self.detail_view, name='%s_%s_detail' % info), # For backwards compatibility (was the change url before 1.9) # url(r'^(.+)/$', RedirectView.as_view(pattern_name='%s:%s_%s_change' % ((self.backend_site.name,) + info))), ] urlpatterns += self.another_urls() return urlpatterns @property def urls(self): return self.get_urls()
class ChangeList(object): def __init__(self, request, arya_modal, list_display, result_list, model_cls, list_filter, actions): self.request = request self.list_display = list_display self.list_filter = list_filter self.model_cls = model_cls self.arya_modal = arya_modal self.actions = actions all_count = result_list.count() query_params = copy.copy(request.GET) query_params._mutable = True self.pager = Page(self.request.GET.get('page'), all_count, base_url=self.arya_modal.changelist_url(), query_params=query_params) self.result_list = result_list[self.pager.start:self.pager.end] def add_btn(self): """ 列表页面定制新建数据按钮 :return: """ add_url = reverse( '%s:%s_%s_add' % (self.arya_modal.site.namespace, self.arya_modal.app_label, self.arya_modal.model_name)) _change = QueryDict(mutable=True) _change['_change_filter'] = self.request.GET.urlencode() tpl = "<a class='btn btn-success' style='float:right' href='{0}?{1}'><span class='glyphicon glyphicon-share-alt' aria-hidden='true'></span> 新建数据</a>".format( add_url, _change.urlencode()) return mark_safe(tpl) def gen_list_filter(self): for option in self.list_filter: if option.is_func: data_list = option.field_or_func(self) else: _field = self.model_cls._meta.get_field(option.field_or_func) if isinstance(_field, ForeignKey): data_list = FilterList(option, self, _field.related_model.objects.all(), self.request.GET,is_foreign=True) elif isinstance(_field, ManyToManyField): data_list = FilterList(option, self, _field.related_model.objects.all(), self.request.GET,is_foreign=True) else: data_list = FilterList(option, self, _field.model.objects.all(), self.request.GET) yield data_list
class FilterList(object): """ 组合搜索项 """ def __init__(self, option, change_list, data_list, param_dict=None,is_foreign=False): self.option = option self.data_list = data_list self.param_dict = copy.deepcopy(param_dict) self.param_dict._mutable = True self.change_list = change_list self.is_foreign = is_foreign def __iter__(self): base_url = self.change_list.arya_modal.changelist_url() tpl = "<a href='{0}' class='{1}'>{2}</a>" # 全部 if self.option.name in self.param_dict: pop_value = self.param_dict.pop(self.option.name) url = "{0}?{1}".format(base_url, self.param_dict.urlencode()) val = tpl.format(url, '', '全部') self.param_dict.setlist(self.option.name, pop_value) else: url = "{0}?{1}".format(base_url, self.param_dict.urlencode()) val = tpl.format(url, 'active', '全部') yield mark_safe("<div class='whole'>") yield mark_safe(val) yield mark_safe("</div>") yield mark_safe("<div class='others'>") tmp_set = set() for obj in self.data_list: param_dict = copy.deepcopy(self.param_dict) # pk = getattr(obj, self.option.val_func_name)() if self.option.val_func_name else obj.pk print(getattr(obj,self.option.name),type(getattr(obj,self.option.name))) pk = getattr(obj,self.option.name) if not self.is_foreign else getattr(obj, self.option.val_func_name)() if self.option.val_func_name else obj.pk pk = str(pk) # text = getattr(obj, self.option.text_func_name)() if self.option.text_func_name else str(obj) text = getattr(obj,self.option.name) if not self.is_foreign else getattr(obj, self.option.text_func_name)() if self.option.text_func_name else str(obj) if text not in tmp_set: tmp_set.add(text) exist = False if pk in param_dict.getlist(self.option.name): exist = True if self.option.is_multi: if exist: tmp = param_dict.getlist(self.option.name) tmp.remove(pk) param_dict.setlist(self.option.name,tmp) else: param_dict.appendlist(self.option.name, pk) else: if exist: param_dict.pop(self.option.name) else: param_dict[self.option.name] = pk url = "{0}?{1}".format(base_url, param_dict.urlencode()) val = tpl.format(url, 'active' if exist else '', text) yield mark_safe(val) yield mark_safe("</div>") class FilterOption(object): def __init__(self, field_or_func, is_multi=False, text_func_name=None, val_func_name=None): """ :param field: 字段名称或函数 :param is_multi: 是否支持多选 :param text_func_name: 在Model中定义函数,显示文本名称,默认使用 str(对象) :param val_func_name: 在Model中定义函数,显示文本名称,默认使用 对象.pk """ self.field_or_func = field_or_func self.is_multi = is_multi self.text_func_name = text_func_name self.val_func_name = val_func_name @property def is_func(self): if isinstance(self.field_or_func, FunctionType): return True @property def name(self): if self.is_func: return self.field_or_func.__name__ else: return self.field_or_func
Fork wupeiqi的pro_admin,结合rbac:https://github.com/fat39/pro_admin
开发过程
1、最简
from django.apps import AppConfig class MyaryaConfig(AppConfig): name = 'myarya' def ready(self): super(MyaryaConfig, self).ready() from django.utils.module_loading import autodiscover_modules autodiscover_modules("myarya")
# -*- coding:utf-8 -*- from django.urls import re_path from django.shortcuts import HttpResponse class MyaryaSite(): def __init__(self): self._registry = {} # model_class class -> admin_class instance @property def urls(self): return self.get_urls() def get_urls(self): urlpatterns = [ re_path("",self.index,name="abc") ] return urlpatterns,"testapp_name","testnamespace" # return urlpatterns,app_name,namespace def register(self,model_class,v): self._registry[model_class] = v def index(self): return HttpResponse("index") site = MyaryaSite()
"""tmp_dj URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path,re_path,include from myarya.service import v1 as my_v1 urlpatterns = [ path('admin/', admin.site.urls), re_path("myarya/",my_v1.site.urls), ]
2、增加BaseMyaryaModel
BaseMyaryaModel是给detail、delete、add生成url的
from django.contrib import admin from django.urls import path,re_path,include from myarya.service import v1 as my_v1 urlpatterns = [ re_path("^myarya/",my_v1.site.urls), ]
# -*- coding:utf-8 -*- from django.urls import re_path,include from django.shortcuts import HttpResponse,render from django.template.response import TemplateResponse from myarya.utils.pagination import Page class BaseMyaryaModel(): def __init__(self,model_class,site): self.model_class = model_class self.site = site @property def urls(self): return self.get_urls() def get_urls(self): app_label = self.model_class._meta.app_label model_name = self.model_class._meta.model_name urlpatterns = [ re_path("^$",self.changelist,name="{}_{}_changelist".format(app_label,model_name)) ] return urlpatterns def changelist(self,request): return HttpResponse("myarya changelist") class MyaryaSite(): def __init__(self,app_name="myarya",namespace="myarya"): self._registry = {} # model_class class -> admin_class instance self.app_name = app_name self.namespace = namespace @property def urls(self): return self.get_urls(),self.app_name,self.namespace def get_urls(self): urlpatterns = [ re_path("^index/$",self.index,name="index") ] for model_class,myaryamodel in self._registry.items(): urlpatterns.append( re_path("{}/{}/".format(model_class._meta.app_label,model_class._meta.model_name),include(myaryamodel.urls)) ) return urlpatterns # return urlpatterns,app_name,namespace # 把这个挪到self.urls def register(self,model_class,myaryamodel=BaseMyaryaModel): self._registry[model_class] = myaryamodel(model_class,self) def index(self,request): return HttpResponse("myarya index") def test(self,request): return HttpResponse("myarya test") site = MyaryaSite()
3、可以访问所有items的页面
# -*- coding:utf-8 -*- from django.urls import re_path,include from django.shortcuts import HttpResponse,render from django.template.response import TemplateResponse from myarya.utils.pagination import Page from django.urls import reverse class Items(): def __init__(self, objs,myaryamodel): request = myaryamodel.request query_params = request.GET.copy() query_params._mutable = True self.page = Page(current_page=request.GET.get("page"), all_count=objs.count(), base_url=request.path, query_params=query_params) self.objs_to_display = objs[self.page.start:self.page.end] self.myaryamodel = myaryamodel class BaseMyaryaModel(): def __init__(self,model_class,site): self.model_class = model_class self.model_name = model_class._meta.model_name self.site = site list_display = "__str__" @property def urls(self): return self.get_urls() def get_urls(self): app_label = self.model_class._meta.app_label model_name = self.model_class._meta.model_name urlpatterns = [ re_path("^$",self.changelist_view,name="{}_{}_changelist".format(app_label,model_name)), re_path("^add/$",self.add_view,name="{}_{}_add".format(app_label,model_name)), re_path("^(\d+)/detail/$",self.detail_view,name="{}_{}_detail".format(app_label,model_name)) ] return urlpatterns def get_models_query_params(self,query_params): query_params = query_params.copy() query_params._mutable = True def changelist_view(self,request): self.request = request objs = self.model_class.objects.all() items = Items(objs,self) context = { "items":items } return TemplateResponse(request,"changelist.html",context=context) return render(request,"changelist.html",context=context) return HttpResponse("changelist page") def add_view(self,request): return TemplateResponse(request,"add.html") def detail_view(self,request,pk): obj = self.model_class.objects.filter(pk=pk).first() context = { "obj":obj } return TemplateResponse(request,"detail.html",context=context) class MyaryaSite(): def __init__(self,app_name="myarya",namespace="myarya"): self._registry = {} # model_class class -> admin_class instance self.app_name = app_name self.namespace = namespace @property def urls(self): return self.get_urls(),self.app_name,self.namespace def get_urls(self): urlpatterns = [ re_path("^index/$",self.index,name="index") ] for model_class,myaryamodel in self._registry.items(): urlpatterns.append( re_path("{}/{}/".format(model_class._meta.app_label,model_class._meta.model_name),include(myaryamodel.urls)) ) return urlpatterns # return urlpatterns,app_name,namespace # 把这个挪到self.urls def register(self,model_class,myaryamodel=BaseMyaryaModel): self._registry[model_class] = myaryamodel(model_class,self) def index(self,request): return HttpResponse("myarya index") def test(self,request): return HttpResponse("myarya test") site = MyaryaSite()
{% load static %} {% load font_table %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src={% static 'myarya/js/jquery-1.12.4.js' %}></script> <link rel="stylesheet" href="{% static 'myarya/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> </head> <body> {# {% font_table items.objs_to_display %}#} {% font_table items %} <nav aria-label="Page navigation"> <ul class="pagination"> {{ items.page.page_html|safe }} </ul> </nav> </body> </html>
# -*- coding:utf-8 -*- from django.template import Library from types import FunctionType register = Library() def table_headers(items): if items.myaryamodel.list_display == "__str__": yield items.myaryamodel.model_name else: for col in items.myaryamodel.list_display: if isinstance(col,FunctionType): yield col(items.myaryamodel,is_header=True) else: yield items.myaryamodel.model_class._meta.get_field(col).verbose_name def table_body(items): for obj in items.objs_to_display: if items.myaryamodel.list_display == "__str__": yield [str(obj)] else: yield [col(items.myaryamodel) if isinstance(col,FunctionType) else getattr(obj,col) for col in items.myaryamodel.list_display] @register.inclusion_tag("font_table.html") def font_table(items): return { "table_headers":table_headers(items), "table_body":table_body(items), }
4、在数据列表页面增加筛选
简易版:把filter直接写在Items类,忘保存了
现版:Filter类、FilterOption类,涉及单选多选,没加上css
# #!/usr/bin/env python # # -*- coding:utf-8 -*- # import copy # import json # import urllib.parse # from django.template.response import TemplateResponse, SimpleTemplateResponse # from django.shortcuts import redirect # from django.urls import reverse # from django.utils.safestring import mark_safe # from django.http.request import QueryDict # from django.forms import Form, ModelForm # from django.forms import fields # from django.forms import widgets # from django.db.models import ForeignKey, ManyToManyField # from arya.utils.pagination import Page # from types import FunctionType # # from django.http.request import QueryDict # # def model_to_dict(instance, fields=None, exclude=None): # from itertools import chain # opts = instance._meta # data = {} # for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many): # print(f, type(f)) # if not getattr(f, 'editable', False): # continue # if fields and f.name not in fields: # continue # if exclude and f.name in exclude: # continue # if type(f) == ForeignKey: # data[f.name + "_id"] = f.value_from_object(instance) # else: # data[f.name] = f.value_from_object(instance) # return data # # # class FilterList(object): # """ # 组合搜索项 # """ # # def __init__(self, option, change_list, data_list, param_dict=None): # self.option = option # # self.data_list = data_list # # self.param_dict = copy.deepcopy(param_dict) # # self.param_dict._mutable = True # # self.change_list = change_list # # def __iter__(self): # # base_url = self.change_list.arya_modal.changelist_url() # tpl = "<a href='{0}' class='{1}'>{2}</a>" # # 全部 # if self.option.name in self.param_dict: # pop_value = self.param_dict.pop(self.option.name) # url = "{0}?{1}".format(base_url, self.param_dict.urlencode()) # val = tpl.format(url, '', '全部') # self.param_dict.setlist(self.option.name, pop_value) # else: # url = "{0}?{1}".format(base_url, self.param_dict.urlencode()) # val = tpl.format(url, 'active', '全部') # yield mark_safe("<div class='whole'>") # yield mark_safe(val) # yield mark_safe("</div>") # # yield mark_safe("<div class='others'>") # for obj in self.data_list: # param_dict = copy.deepcopy(self.param_dict) # # pk = getattr(obj, self.option.val_func_name)() if self.option.val_func_name else obj.pk # pk = str(pk) # # text = getattr(obj, self.option.text_func_name)() if self.option.text_func_name else str(obj) # # exist = False # if pk in param_dict.getlist(self.option.name): # exist = True # tmp_list = param_dict.getlist(self.option.name) # tmp_list.remove(pk) # param_dict.setlist(self.option.name,tmp_list) # # if self.option.is_multi: # exist or param_dict.appendlist(self.option.name, pk) # else: # if not exist: # param_dict[self.option.name] = pk # url = "{0}?{1}".format(base_url, param_dict.urlencode()) # val = tpl.format(url, 'active' if exist else '', text) # yield mark_safe(val) # yield mark_safe("</div>") # # # class FilterOption(object): # def __init__(self, field_or_func, is_multi=False, text_func_name=None, val_func_name=None): # """ # :param field: 字段名称或函数 # :param is_multi: 是否支持多选 # :param text_func_name: 在Model中定义函数,显示文本名称,默认使用 str(对象) # :param val_func_name: 在Model中定义函数,显示文本名称,默认使用 对象.pk # """ # self.field_or_func = field_or_func # self.is_multi = is_multi # self.text_func_name = text_func_name # self.val_func_name = val_func_name # # @property # def is_func(self): # if isinstance(self.field_or_func, FunctionType): # return True # # @property # def name(self): # if self.is_func: # return self.field_or_func.__name__ # else: # return self.field_or_func # # # class ChangeList(object): # def __init__(self, request, arya_modal, list_display, result_list, model_cls, list_filter, actions): # self.request = request # self.list_display = list_display # self.list_filter = list_filter # # self.model_cls = model_cls # self.arya_modal = arya_modal # self.actions = actions # # query_params = copy.deepcopy(request.GET) # query_params._mutable = True # # all_count = result_list.count() # self.pager = Page(self.request.GET.get('page'), all_count,per_page=int(self.request.GET.get("per_page") or 10), base_url=self.arya_modal.changelist_url(), # query_params=query_params) # self.result_list = result_list[self.pager.start:self.pager.end] # # def add_btn(self): # """ # 列表页面定制新建数据按钮 # :return: # """ # add_url = reverse( # '%s:%s_%s_add' % (self.arya_modal.site.namespace, self.arya_modal.app_label, self.arya_modal.model_name)) # # _change = QueryDict(mutable=True) # _change['_change_filter'] = self.request.GET.urlencode() # # tpl = "<a class='btn btn-success' style='float:right' href='{0}?{1}'><span class='glyphicon glyphicon-share-alt' aria-hidden='true'></span> 新建数据</a>".format( # add_url, # _change.urlencode()) # return mark_safe(tpl) # # def gen_list_filter(self): # # for option in self.list_filter: # if option.is_func: # data_list = option.field_or_func(self) # else: # _field = self.model_cls._meta.get_field(option.field_or_func) # if isinstance(_field, ForeignKey): # data_list = FilterList(option, self, _field.related_model.objects.all(), self.request.GET) # elif isinstance(_field, ManyToManyField): # data_list = FilterList(option, self, _field.related_model.objects.all(), self.request.GET) # else: # data_list = FilterList(option, self, _field.model.objects.all(), self.request.GET) # yield data_list # # # class BaseAryaModal(object): # def __init__(self, model_class, site): # self.model_class = model_class # self.app_label = model_class._meta.app_label # self.model_name = model_class._meta.model_name # self.param_key = "_change_filter" # # self.site = site # # self.request = None # # def changelist_param_url(self, query_params): # # redirect_url = "%s?%s" % (reverse('%s:%s_%s' % (self.site.namespace, self.app_label, self.model_name)), # # urllib.parse.urlencode(self.change_list_condition)) # redirect_url = "%s?%s" % ( # reverse('%s:%s_%s_changelist' % (self.site.namespace, self.app_label, self.model_name)), # query_params.urlencode()) # return redirect_url # # def changelist_url(self): # redirect_url = reverse('%s:%s_%s_changelist' % (self.site.namespace, self.app_label, self.model_name)) # return redirect_url # # def another_urls(self): # """ # 钩子函数,用于自定义额外的URL # :return: # """ # return [] # # def get_urls(self): # from django.conf.urls import url # info = self.model_class._meta.app_label, self.model_class._meta.model_name # # urlpatterns = [ # url(r'^$', self.changelist_view, name='%s_%s_changelist' % info), # url(r'^add/$', self.add_view, name='%s_%s_add' % info), # url(r'^(.+)/delete/$', self.delete_view, name='%s_%s_delete' % info), # url(r'^(.+)/change/$', self.change_view, name='%s_%s_change' % info), # url(r'^(.+)/detail/$', self.detail_view, name='%s_%s_detail' % info), # # For backwards compatibility (was the change url before 1.9) # # url(r'^(.+)/$', RedirectView.as_view(pattern_name='%s:%s_%s_change' % ((self.backend_site.name,) + info))), # ] # urlpatterns += self.another_urls() # return urlpatterns # # @property # def urls(self): # return self.get_urls() # # # ########## CURD功能 ########## # # """1. 定制显示列表的Html模板""" # change_list_template = [] # add_form_template = [] # detail_template = [] # change_form_template = [] # # """2. 定制列表中的筛选条件""" # # def get_model_field_name_list(self): # """ # 获取当前model中定义的字段 # :return: # """ # # print(type(self.model_class._meta)) # from django.db.models.options import Options # return [item.name for item in self.model_class._meta.fields] # # def get_model_field_name_list_m2m(self): # return [item.name for item in self.model_class._meta.many_to_many] # # def get_all_model_field_name_list(self): # """ # # 获取当前model中定义的字段(包括反向查找字段) # :return: # """ # return [item.name for item in self.model_class._meta._get_fields()] # # def get_change_list_condition(self, query_params): # # # 获取当前访问的数据类 self.model_class # field_list = self.get_all_model_field_name_list() # condition = {} # for k in query_params: # if k not in field_list: # # raise Exception('条件查询字段%s不合法,合法字段为:%s' % (k, ",".join(field_list))) # continue # condition[k + "__in"] = query_params.getlist(k) # return condition # # """3. 定制数据列表开始""" # # list_display = "__str__" # # """4. 定制Action行为""" # # def delete_action(self, request, queryset): # """ # 定制Action行为 # :param request: # :param queryset: # :return: True表示保留所有条件,False表示回到列表页面 # """ # pk_list = request.POST.getlist('pk') # queryset.filter(id__in=pk_list).delete() # # return True # # delete_action.short_description = "删除选择项" # # # # actions = [delete_action, ] # # """5. 定制添加和编辑页面中的Form组件""" # page_model_form = None # # @property # def get_model_form_cls(self): # model_form_cls = self.page_model_form # if not model_form_cls: # _meta = type('Meta', (object,), {'model': self.model_class, "fields": "__all__"}) # model_form_cls = type('DynamicModelForm', (ModelForm,), {'Meta': _meta}) # return model_form_cls # # """6. 定制查询组合条件""" # list_filter = [] # # """增删改查方法""" # # def changelist_view(self, request): # """ # 显示数据列表 # 1. 数据列表 # 2. 筛选 # 3. 分页 # 4. 是否可编辑 # 5. 搜索 # 6. 定制行为 # :param request: # :return: # """ # self.request = request # result_list = self.model_class.objects.filter(**self.get_change_list_condition(request.GET)) # # if request.method == "POST": # """执行Action行为""" # action = request.POST.get('action') # if not action: # return redirect(self.changelist_param_url(request.GET)) # if getattr(self, action)(request, result_list): # return redirect(self.changelist_param_url(request.GET)) # else: # return redirect(self.changelist_url()) # # change_list = ChangeList(request, self, self.list_display, result_list, self.model_class, self.list_filter, # actions=self.actions) # context = { # 'cl': change_list, # } # return TemplateResponse(request, self.change_list_template or [ # 'arya/%s/%s/change_list.html' % (self.app_label, self.model_name), # 'arya/%s/change_list.html' % self.app_label, # 'arya/change_list.html' # ], context) # # def add_view(self, request): # """ # 添加页面 # :param request: # :return: # """ # # if request.method == 'GET': # form = self.get_model_form_cls() # # elif request.method == "POST": # form = self.get_model_form_cls(data=request.POST, files=request.FILES) # if form.is_valid(): # obj = form.save() # popup_id = request.GET.get("_popup") # if popup_id: # context = {'pk': obj.pk, 'value': str(obj), 'popup_id': popup_id} # return SimpleTemplateResponse('arya/popup_response.html', # {"popup_response_data": json.dumps(context)}) # else: # # _change_filter = request.GET.get('_change_filter') # _change_filter = request.GET.get(self.param_key) # if _change_filter: # change_list_url = "{0}?{1}".format(self.changelist_url(), _change_filter) # else: # change_list_url = self.changelist_url() # return redirect(change_list_url) # else: # raise Exception('当前URL只支持GET/POST方法') # context = { # 'form': form # } # return TemplateResponse(request, self.add_form_template or [ # 'arya/%s/%s/add.html' % (self.app_label, self.model_name), # 'arya/%s/add.html' % self.app_label, # 'arya/add.html' # ], context) # # def delete_view(self, request, pk): # """ # 删除 # :param request: # :param pk: # :return: # """ # self.model_class.objects.filter(pk=pk).delete() # # _change_filter = request.GET.get('_change_filter') # _change_filter = request.GET.get(self.param_key) # if _change_filter: # change_list_url = "{0}?{1}".format(self.changelist_url(), _change_filter) # else: # change_list_url = self.changelist_url() # return redirect(change_list_url) # # def change_view(self, request, pk): # """ # 修改页面 # :param request: # :param pk: # :return: # """ # obj = self.model_class.objects.filter(pk=pk).first() # if request.method == 'GET': # form = self.get_model_form_cls(instance=obj) # elif request.method == 'POST': # form = self.get_model_form_cls(data=request.POST, files=request.FILES, instance=obj) # if form.is_valid(): # form.save() # # 如果修改成功,则跳转回去原来筛选页面 # _change_filter = request.GET.get(self.param_key) # if _change_filter: # change_list_url = "{0}?{1}".format(self.changelist_url(), _change_filter) # else: # change_list_url = self.changelist_url() # return redirect(change_list_url) # else: # raise Exception('当前URL只支持GET/POST方法') # # context = { # 'form': form # } # return TemplateResponse(request, self.change_form_template or [ # 'arya/%s/%s/change.html' % (self.app_label, self.model_name), # 'arya/%s/change.html' % self.app_label, # 'arya/change.html' # ], context) # # def detail_view(self, request, pk): # """ # 查看详细 # :param request: # :param pk: # :return: # """ # row = self.model_class.objects.filter(pk=pk).first() # fields = self.get_model_form_cls.Meta.fields # if fields == '__all__': # fields = self.get_model_field_name_list() # # print(self.get_model_field_name_list_m2m()) # context_ = {} # for name in fields: # val = getattr(row, name) # context_[name] = val # # context = { # # 'row': row # "kv":context_, # } # return TemplateResponse(request, self.change_form_template or [ # 'arya/%s/%s/detail.html' % (self.app_label, self.model_name), # 'arya/%s/detail.html' % self.app_label, # 'arya/detail.html' # ], context) # # # class AryaSite(object): # def __init__(self, app_name='arya', namespace='arya'): # self.app_name = app_name # self.namespace = namespace # self._registry = {} # # def register(self, model_class, arya_model_class=BaseAryaModal): # self._registry[model_class] = arya_model_class(model_class, self) # # def get_urls(self): # from django.conf.urls import url, include # # urlpatterns = [ # url(r'^$', self.index, name='index'), # url(r'^login/$', self.login, name='login'), # url(r'^logout/$', self.logout, name='logout'), # ] # # for model_class, arya_model_obj in self._registry.items(): # urlpatterns += [ # url(r'^%s/%s/' % (model_class._meta.app_label, model_class._meta.model_name), # include(arya_model_obj.urls)) # ] # return urlpatterns # # @property # def urls(self): # """ # 创建URL对应关系 # :return: 元组类型:url关系列表或模块(模块内部必须有urlpatterns属性);app_name;namespace # """ # # return self.get_urls(), self.app_name, self.namespace # # def login(self, request): # """ # 用户登录 # :param request: # :return: # """ # pass # # def logout(self, request): # """ # 用户注销 # :param request: # :return: # """ # pass # # def index(self, request): # """ # 首页 # :param request: # :return: # """ # from django.http import HttpResponse # return HttpResponse("index ok") # pass # # # site = AryaSite() #!/usr/bin/env python # -*- coding:utf-8 -*- import copy import json import urllib.parse from django.template.response import TemplateResponse, SimpleTemplateResponse from django.shortcuts import redirect, render, HttpResponse from django.urls import reverse from django.utils.safestring import mark_safe from django.http.request import QueryDict from django.forms import Form, ModelForm from django.forms import fields from django.forms import widgets from django.db.models import ForeignKey, ManyToManyField from arya.utils.pagination import Page from types import FunctionType from django.http.request import QueryDict def model_to_dict(instance, fields=None, exclude=None): from itertools import chain """ Returns a dict containing the data in ``instance`` suitable for passing as a Form's ``initial`` keyword argument. ``fields`` is an optional list of field names. If provided, only the named fields will be included in the returned dict. ``exclude`` is an optional list of field names. If provided, the named fields will be excluded from the returned dict, even if they are listed in the ``fields`` argument. """ opts = instance._meta data = {} for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many): print(f, type(f)) if not getattr(f, 'editable', False): continue if fields and f.name not in fields: continue if exclude and f.name in exclude: continue if type(f) == ForeignKey: data[f.name + "_id"] = f.value_from_object(instance) else: data[f.name] = f.value_from_object(instance) return data class FilterList(object): """ 组合搜索项 """ def __init__(self, option, change_list, data_list, param_dict=None): self.option = option self.data_list = data_list self.param_dict = copy.deepcopy(param_dict) self.param_dict._mutable = True self.change_list = change_list def __iter__(self): base_url = self.change_list.arya_modal.changelist_url() tpl = "<a href='{0}' class='{1}'>{2}</a>" # 全部 if self.option.name in self.param_dict: pop_value = self.param_dict.pop(self.option.name) url = "{0}?{1}".format(base_url, self.param_dict.urlencode()) val = tpl.format(url, '', '全部') self.param_dict.setlist(self.option.name, pop_value) else: url = "{0}?{1}".format(base_url, self.param_dict.urlencode()) val = tpl.format(url, 'active', '全部') yield mark_safe("<div class='whole'>") yield mark_safe(val) yield mark_safe("</div>") yield mark_safe("<div class='others'>") for obj in self.data_list: param_dict = copy.deepcopy(self.param_dict) pk = getattr(obj, self.option.val_func_name)() if self.option.val_func_name else obj.pk pk = str(pk) text = getattr(obj, self.option.text_func_name)() if self.option.text_func_name else str(obj) exist = False if pk in param_dict.getlist(self.option.name): exist = True if self.option.is_multi: if exist: param_dict.getlist(self.option.name).remove(pk) else: param_dict.appendlist(self.option.name, pk) else: param_dict[self.option.name] = pk url = "{0}?{1}".format(base_url, param_dict.urlencode()) val = tpl.format(url, 'active' if exist else '', text) yield mark_safe(val) yield mark_safe("</div>") class FilterOption(object): def __init__(self, field_or_func, is_multi=False, text_func_name=None, val_func_name=None): """ :param field: 字段名称或函数 :param is_multi: 是否支持多选 :param text_func_name: 在Model中定义函数,显示文本名称,默认使用 str(对象) :param val_func_name: 在Model中定义函数,显示文本名称,默认使用 对象.pk """ self.field_or_func = field_or_func self.is_multi = is_multi self.text_func_name = text_func_name self.val_func_name = val_func_name @property def is_func(self): if isinstance(self.field_or_func, FunctionType): return True @property def name(self): if self.is_func: return self.field_or_func.__name__ else: return self.field_or_func class ChangeList(object): def __init__(self, request, arya_modal, list_display, result_list, model_cls, list_filter, actions): self.request = request self.list_display = list_display self.list_filter = list_filter self.model_cls = model_cls self.arya_modal = arya_modal self.actions = actions all_count = result_list.count() query_params = copy.copy(request.GET) query_params._mutable = True self.pager = Page(self.request.GET.get('page'), all_count, base_url=self.arya_modal.changelist_url(), query_params=query_params) self.result_list = result_list[self.pager.start:self.pager.end] def add_btn(self): """ 列表页面定制新建数据按钮 :return: """ add_url = reverse( '%s:%s_%s_add' % (self.arya_modal.site.namespace, self.arya_modal.app_label, self.arya_modal.model_name)) _change = QueryDict(mutable=True) _change['_change_filter'] = self.request.GET.urlencode() tpl = "<a class='btn btn-success' style='float:right' href='{0}?{1}'><span class='glyphicon glyphicon-share-alt' aria-hidden='true'></span> 新建数据</a>".format( add_url, _change.urlencode()) return mark_safe(tpl) def gen_list_filter(self): for option in self.list_filter: if option.is_func: data_list = option.field_or_func(self) else: _field = self.model_cls._meta.get_field(option.field_or_func) if isinstance(_field, ForeignKey): data_list = FilterList(option, self, _field.related_model.objects.all(), self.request.GET) elif isinstance(_field, ManyToManyField): data_list = FilterList(option, self, _field.related_model.objects.all(), self.request.GET) else: data_list = FilterList(option, self, _field.model.objects.all(), self.request.GET) yield data_list class BaseAryaModal(object): def __init__(self, model_class, site): self.model_class = model_class self.app_label = model_class._meta.app_label self.model_name = model_class._meta.model_name self.site = site self.request = None def changelist_param_url(self, query_params): # redirect_url = "%s?%s" % (reverse('%s:%s_%s' % (self.site.namespace, self.app_label, self.model_name)), # urllib.parse.urlencode(self.change_list_condition)) redirect_url = "%s?%s" % ( reverse('%s:%s_%s_changelist' % (self.site.namespace, self.app_label, self.model_name)), query_params.urlencode()) return redirect_url def changelist_url(self): redirect_url = reverse('%s:%s_%s_changelist' % (self.site.namespace, self.app_label, self.model_name)) return redirect_url def another_urls(self): """ 钩子函数,用于自定义额外的URL :return: """ return [] def get_urls(self): from django.conf.urls import url info = self.model_class._meta.app_label, self.model_class._meta.model_name urlpatterns = [ url(r'^$', self.changelist_view, name='%s_%s_changelist' % info), url(r'^add/$', self.add_view, name='%s_%s_add' % info), url(r'^(.+)/delete/$', self.delete_view, name='%s_%s_delete' % info), url(r'^(.+)/change/$', self.change_view, name='%s_%s_change' % info), url(r'^(.+)/detail/$', self.detail_view, name='%s_%s_detail' % info), # For backwards compatibility (was the change url before 1.9) # url(r'^(.+)/$', RedirectView.as_view(pattern_name='%s:%s_%s_change' % ((self.backend_site.name,) + info))), ] urlpatterns += self.another_urls() return urlpatterns @property def urls(self): return self.get_urls() # ########## CURD功能 ########## """1. 定制显示列表的Html模板""" change_list_template = [] add_form_template = [] detail_template = [] change_form_template = [] """2. 定制列表中的筛选条件""" def get_model_field_name_list(self): """ 获取当前model中定义的字段 :return: """ # print(type(self.model_class._meta)) from django.db.models.options import Options return [item.name for item in self.model_class._meta.fields] def get_model_field_name_list_m2m(self): return [item.name for item in self.model_class._meta.many_to_many] def get_all_model_field_name_list(self): """ # 获取当前model中定义的字段(包括反向查找字段) :return: """ return [item.name for item in self.model_class._meta._get_fields()] def get_change_list_condition(self, query_params): field_list = self.get_all_model_field_name_list() condition = {} for k in query_params: if k not in field_list: # raise Exception('条件查询字段%s不合法,合法字段为:%s' % (k, ",".join(field_list))) continue condition[k + "__in"] = query_params.getlist(k) return condition """3. 定制数据列表开始""" list_display = "__str__" """4. 定制Action行为""" def delete_action(self, request, queryset): """ 定制Action行为 :param request: :param queryset: :return: True表示保留所有条件,False表示回到列表页面 """ pk_list = request.POST.getlist('pk') queryset.filter(id__in=pk_list).delete() return True delete_action.short_description = "删除选择项" actions = [delete_action, ] """5. 定制添加和编辑页面中的Form组件""" page_model_form = None @property def get_model_form_cls(self): model_form_cls = self.page_model_form if not model_form_cls: _meta = type('Meta', (object,), {'model': self.model_class, "fields": "__all__"}) model_form_cls = type('DynamicModelForm', (ModelForm,), {'Meta': _meta}) return model_form_cls """6. 定制查询组合条件""" list_filter = [] """增删改查方法""" def changelist_view(self, request): """ 显示数据列表 1. 数据列表 2. 筛选 3. 分页 4. 是否可编辑 5. 搜索 6. 定制行为 :param request: :return: """ self.request = request result_list = self.model_class.objects.filter(**self.get_change_list_condition(request.GET)) if request.method == "POST": """执行Action行为""" action = request.POST.get('action') if not action: return redirect(self.changelist_param_url(request.GET)) if getattr(self, action)(request, result_list): return redirect(self.changelist_param_url(request.GET)) else: return redirect(self.changelist_url()) change_list = ChangeList(request, self, self.list_display, result_list, self.model_class, self.list_filter, actions=self.actions) context = { 'cl': change_list, } return TemplateResponse(request, self.change_list_template or [ 'arya/%s/%s/change_list.html' % (self.app_label, self.model_name), 'arya/%s/change_list.html' % self.app_label, 'arya/change_list.html' ], context) def add_view(self, request): """ 添加页面 :param request: :return: """ if request.method == 'GET': form = self.get_model_form_cls() elif request.method == "POST": form = self.get_model_form_cls(data=request.POST, files=request.FILES) if form.is_valid(): obj = form.save() popup_id = request.GET.get("_popup") if popup_id: context = {'pk': obj.pk, 'value': str(obj), 'popup_id': popup_id} return SimpleTemplateResponse('arya/popup_response.html', {"popup_response_data": json.dumps(context)}) else: _change_filter = request.GET.get('_change_filter') if _change_filter: change_list_url = "{0}?{1}".format(self.changelist_url(), _change_filter) else: change_list_url = self.changelist_url() return redirect(change_list_url) else: raise Exception('当前URL只支持GET/POST方法') context = { 'form': form } return TemplateResponse(request, self.add_form_template or [ 'arya/%s/%s/add.html' % (self.app_label, self.model_name), 'arya/%s/add.html' % self.app_label, 'arya/add.html' ], context) def delete_view(self, request, pk): """ 删除 :param request: :param pk: :return: """ self.model_class.objects.filter(pk=pk).delete() _change_filter = request.GET.get('_change_filter') if _change_filter: change_list_url = "{0}?{1}".format(self.changelist_url(), _change_filter) else: change_list_url = self.changelist_url() return redirect(change_list_url) def change_view(self, request, pk): """ 修改页面 :param request: :param pk: :return: """ obj = self.model_class.objects.filter(pk=pk).first() if request.method == 'GET': form = self.get_model_form_cls(instance=obj) elif request.method == 'POST': form = self.get_model_form_cls(data=request.POST, files=request.FILES, instance=obj) if form.is_valid(): form.save() # 如果修改成功,则跳转回去原来筛选页面 _change_filter = request.GET.get('_change_filter') if _change_filter: change_list_url = "{0}?{1}".format(self.changelist_url(), _change_filter) else: change_list_url = self.changelist_url() return redirect(change_list_url) else: raise Exception('当前URL只支持GET/POST方法') context = { 'form': form } return TemplateResponse(request, self.change_form_template or [ 'arya/%s/%s/change.html' % (self.app_label, self.model_name), 'arya/%s/change.html' % self.app_label, 'arya/change.html' ], context) def detail_view(self, request, pk): """ 查看详细 :param request: :param pk: :return: """ row = self.model_class.objects.filter(pk=pk).first() fields = self.get_model_form_cls.Meta.fields if fields == '__all__': fields = self.get_model_field_name_list() # print(self.get_model_field_name_list_m2m()) for name in fields: val = getattr(row, name) # print(name, val) context = { 'row': row } return TemplateResponse(request, self.change_form_template or [ 'arya/%s/%s/detail.html' % (self.app_label, self.model_name), 'arya/%s/detail.html' % self.app_label, 'arya/detail.html' ], context) class AryaSite(object): def __init__(self, app_name='arya', namespace='arya'): self.app_name = app_name self.namespace = namespace self._registry = {} def register(self, model_class, arya_model_class=BaseAryaModal): self._registry[model_class] = arya_model_class(model_class, self) def get_urls(self): from django.conf.urls import url, include urlpatterns = [ url(r'^$', self.index, name='index'), url(r'^login/$', self.login, name='login'), url(r'^logout/$', self.logout, name='logout'), ] for model_class, arya_model_obj in self._registry.items(): urlpatterns += [ url(r'^%s/%s/' % (model_class._meta.app_label, model_class._meta.model_name), include(arya_model_obj.urls)) ] return urlpatterns @property def urls(self): """ 创建URL对应关系 :return: 元组类型:url关系列表或模块(模块内部必须有urlpatterns属性);app_name;namespace """ return self.get_urls(), self.app_name, self.namespace def login(self, request): """ 用户登录 :param request: :return: """ from arya import models from arya.service import rbac # 测试 # obj = models.User.objects.get(id=1) # rbac.initial_permission(request, obj) # 初始化权限信息 # # return HttpResponse('Login') if request.method == 'GET': return render(request, 'login.html') else: from arya import models from arya.service import rbac user = request.POST.get('username') pwd = request.POST.get('password') obj = models.User.objects.filter(username=user, password=pwd).first() if obj: rbac.initial_permission(request, obj) return redirect('/arya/') else: return render(request, 'login.html') def logout(self, request): """ 用户注销 :param request: :return: """ pass def index(self, request): """ 首页 :param request: :return: """ return render(request, 'arya/index.html') site = AryaSite()
{% load static %} {% load font_table %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src={% static 'myarya/js/jquery-1.12.4.js' %}></script> <link rel="stylesheet" href="{% static 'myarya/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> </head> <body> {% for list_filter in items.gen_list_filter %} {% for option in list_filter %} {{ option|safe }} {% endfor %} {% endfor %} {% font_table items %} <nav aria-label="Page navigation"> <ul class="pagination"> {{ items.page.page_html|safe }} </ul> </nav> </body> </html>
# -*- coding:utf-8 -*-
from myarya.service import v1
from myarya.service.v1 import FilterOption
from . import models
class MovieMyaryModel(v1.BaseMyaryaModel):
def custom_field(self,obj=None,is_header=False):
if is_header:
return "custom_field"
else:
return "haha"
list_display = [custom_field,"name","url"]
list_filter = [
FilterOption("district",is_multi=True),
# FilterOption("district"),
]
v1.site.register(models.Movie,MovieMyaryModel)
v1.site.register(models.Actors)
5、添加“操作”栏,添加add按钮
# -*- coding:utf-8 -*- from django.http.request import QueryDict from django.urls import re_path,include from django.shortcuts import HttpResponse,render from django.template.response import TemplateResponse from myarya.utils.pagination import Page from django.urls import reverse from django.db.models.fields import Field from django.db.models.fields.related import ForeignKey from django.db.models.fields.related import ManyToManyField from django.utils.safestring import mark_safe from types import FunctionType import copy class FilterOption(): def __init__(self,field_or_func,is_multi=False,): self.field_or_func = field_or_func self.is_multi = is_multi @property def is_func(self): if isinstance(self.field_or_func,FunctionType): return True @property def name(self): if isinstance(self.field_or_func, FunctionType): return self.field_or_func.__name__ else: return self.field_or_func class Filter(): def __init__(self,option,request,data_list,changelist,is_foreign=False): self.option = option self.data_list = data_list self.is_foreign = is_foreign self.request = request self.query_params = copy.deepcopy(self.request.GET) self.query_params._mutable = True self.changelist = changelist def __iter__(self): query_params = copy.deepcopy(self.query_params) # base_url = self.changelist.myaryamodel.changelist_url base_url = self.request.path if self.option.name in query_params: query_params.pop(self.option.name) whole_url = "{}?{}".format(base_url,query_params.urlencode()) yield mark_safe("<div class='whole'><a href='{}' class=''>全部</a></div>".format(whole_url)) else: whole_url = "{}?{}".format(base_url, query_params.urlencode()) yield mark_safe("<div class='whole'><a href='{}' class='active'>全部</a></div>".format(whole_url)) yield mark_safe("<div>") text_set = set() for obj in self.data_list: query_params = copy.deepcopy(self.query_params) text = str(obj) if self.is_foreign else getattr(obj, self.option.name) if text not in text_set: text_set.add(text) val = str(obj.pk if self.is_foreign else text) tmp_list = query_params.getlist(self.option.name) if val not in tmp_list: exist_flag = False else: exist_flag = True if self.option.is_multi: if not exist_flag: tmp_list.append(val) query_params.setlist(self.option.name, tmp_list) else: tmp_list.remove(val) query_params.setlist(self.option.name, tmp_list) else: if not exist_flag: query_params.setlist(self.option.name,[val]) url = "{}?{}".format(base_url, query_params.urlencode()) yield mark_safe("<a href='{}' class='{}'>{}</a>".format(url,"active" if exist_flag else "", text)) yield mark_safe("</div>") class Items(): def __init__(self, objs,myaryamodel): self.myaryamodel = myaryamodel self.model_class = myaryamodel.model_class self.request = myaryamodel.request self.list_filter = myaryamodel.list_filter self.query_params = copy.deepcopy(self.request.GET) self.query_params._mutable = True self.page = Page(current_page=self.request.GET.get("page"), all_count=objs.count(), base_url=self.request.path, query_params=self.query_params) self.objs_to_display = objs[self.page.start:self.page.end] def add_btn(self): add_url = reverse( '%s:%s_%s_add' % (self.myaryamodel.site.namespace, self.myaryamodel.app_label, self.myaryamodel.model_name)) query_param = copy.deepcopy(self.request.GET) _query_param = QueryDict(mutable=True) _query_param["_changelist"] = query_param.urlencode() url = "{}?{}".format(add_url,_query_param.urlencode()) return mark_safe("<a href='{}'>添加条目</a>".format(url)) @property def gen_list_filter(self): for option in self.list_filter: field = self.model_class._meta.get_field(option.name) if isinstance(field, ManyToManyField): data_list = Filter(option,self.request,field.related_model.objects.all(),self,is_foreign=True) elif isinstance(field, ForeignKey): data_list = Filter(option,self.request,field.related_model.objects.all(),self,is_foreign=True) elif isinstance(field, Field): data_list = Filter(option,self.request,field.model.objects.all(),self) else: data_list = Filter(option,self.request, field.model.objects.all(),self) yield data_list class BaseMyaryaModel(): def __init__(self,model_class,site): self.model_class = model_class self.app_label = self.model_class._meta.app_label self.model_name = self.model_class._meta.model_name self.site = site list_display = "__str__" @property def urls(self): return self.get_urls() def get_urls(self): urlpatterns = [ re_path("^$",self.changelist_view,name="{}_{}_changelist".format(self.app_label,self.model_name)), re_path("^add/$",self.add_view,name="{}_{}_add".format(self.app_label,self.model_name)), re_path("^(\d+)/edit/$",self.edit_view,name="{}_{}_edit".format(self.app_label,self.model_name)), re_path("^(\d+)/detail/$",self.detail_view,name="{}_{}_detail".format(self.app_label,self.model_name)), re_path("^(\d+)/delete/$",self.delete_view,name="{}_{}_delete".format(self.app_label,self.model_name)) ] return urlpatterns @property def changelist_url(self): return reverse('%s:%s_%s_changelist' % (self.site.namespace, self.app_label, self.model_name)) def changelist_view(self,request): self.request = request objs = self.model_class.objects.all() items = Items(objs,self) context = { "items":items } return TemplateResponse(request,"changelist.html",context=context) return render(request,"changelist.html",context=context) return HttpResponse("changelist page") def add_view(self,request): return TemplateResponse(request,"add.html") def edit_view(self,request,pk): return HttpResponse("123") def detail_view(self,request,pk): obj = self.model_class.objects.filter(pk=pk).first() context = { "obj":obj } return TemplateResponse(request,"detail.html",context=context) def delete_view(self,request,pk): return HttpResponse("123") list_filter = [] class MyaryaSite(): def __init__(self,app_name="myarya",namespace="myarya"): self._registry = {} # model_class class -> admin_class instance self.app_name = app_name self.namespace = namespace @property def urls(self): return self.get_urls(),self.app_name,self.namespace def get_urls(self): urlpatterns = [ re_path("^index/$",self.index,name="index") ] for model_class,myaryamodel in self._registry.items(): urlpatterns.append( re_path("{}/{}/".format(model_class._meta.app_label,model_class._meta.model_name),include(myaryamodel.urls)) ) return urlpatterns # return urlpatterns,app_name,namespace # 把这个挪到self.urls def register(self,model_class,myaryamodel=BaseMyaryaModel): self._registry[model_class] = myaryamodel(model_class,self) def index(self,request): return HttpResponse("myarya index") def test(self,request): return HttpResponse("myarya test") site = MyaryaSite()
# -*- coding:utf-8 -*- from myarya.service import v1 from myarya.service.v1 import FilterOption from . import models from django.urls import reverse import copy from django.http.request import QueryDict from django.utils.safestring import mark_safe class MovieMyaryModel(v1.BaseMyaryaModel): def custom_field(self,obj=None,is_header=False): if is_header: return "custom_field" else: return "haha" def edit_field(self,obj=None,is_header=False): if is_header: return "操作" else: edit_url = reverse('{0}:{1}_{2}_edit'.format(self.site.namespace, self.app_label, self.model_name), args=(obj.pk,)) del_url = reverse('{0}:{1}_{2}_delete'.format(self.site.namespace, self.app_label, self.model_name), args=(obj.pk,)) detail_url = reverse('{0}:{1}_{2}_detail'.format(self.site.namespace, self.app_label, self.model_name), args=(obj.pk,)) query_param = copy.deepcopy(self.request.GET) _query_param = QueryDict(mutable=True) _query_param["_changelist"] = query_param.urlencode() url_format = "{}?"+_query_param.urlencode() htm_str = "<a href='{}'>编辑</a>|<a href='{}'>删除</a>|<a href='{}'>查看详细</a>".format( url_format.format(edit_url), url_format.format(del_url), url_format.format(detail_url), ) return mark_safe(htm_str) list_display = [custom_field,"name","url",edit_field] list_filter = [ FilterOption("district",is_multi=True), # FilterOption("district"), ] v1.site.register(models.Movie,MovieMyaryModel) v1.site.register(models.Actors)
{% load static %} {% load font_table %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src={% static 'myarya/js/jquery-1.12.4.js' %}></script> <link rel="stylesheet" href="{% static 'myarya/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> </head> <body> {% for list_filter in items.gen_list_filter %} {% for option in list_filter %} {{ option|safe }} {% endfor %} {% endfor %} <div>{{ items.add_btn }}</div> {% font_table items %} <nav aria-label="Page navigation"> <ul class="pagination"> {{ items.page.page_html|safe }} </ul> </nav> </body> </html>