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

urls相关部分

# 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)

register把models与arya关联起来

# 对每一个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()

BaseAryaModal的url部分

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

BaseAryaModal的主页面部分,把所有items、filter、actions封装到对象ChangeList里,直接在页面分别引用

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

单独创建对象FilterList,用以iter出筛选框。FilterOption则记录用户arya里该单项筛选条件的属性

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")

tmp_dj(项目名称,下同)/myarya/apps.py

# -*- 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/myarya/service/v1.py

"""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),
]

tmp_dj/tmp_dj/urls.py

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),
]

tmp_dj/tmp_dj/urls.py

# -*- 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()

tmp_dj/myarya/service/v1.py

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()

tmp_dj/myarya/service/v1.py

{% 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>

tmp_dj/myarya/templates/changelist.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),
}

tmp_dj/myarya/templatetags/font_table.py

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()

tmp_dj/myarya/service/v1.py

{% 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>

tmp_dj/myarya/templates/changelist.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)

tmp_dj/其他app/myarya.py

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("") 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("") 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()

tmp_dj/myarya/service/v1.py

# -*- 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)

tmp_dj/其他app/myarya.py

{% 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>

tmp_dj/myarya/templates/changelist.html

django_models后台管理myarya的更多相关文章

  1. MVC5 网站开发之七 用户功能 1、角色的后台管理

    角色是网站中都有的一个功能,用来区分用户的类型.划分用户的权限,这次实现角色列表浏览.角色添加.角色修改和角色删除. 目录 奔跑吧,代码小哥! MVC5网站开发之一 总体概述 MVC5 网站开发之二 ...

  2. 后台管理UI的选择

    最近要做一个企业的OA系统,以前一直使用EasyUI,一切都好,但感觉有点土了,想换成现在流行的Bootstrap为基础的后台UI风格,想满足的条件应该达到如下几个: 1.美观.大方.简洁 2.兼容I ...

  3. Django-Admin后台管理

    Rhel6.5 Django1.10 Python3.5 应用环境:Python+Virtualenv(Python Virtualenv运行Django环境配置) Django-Admin后台管理 ...

  4. 集成一体化的移动POS开单扫描解决方案--"移动开单掌上POS"。它集后台管理软件

    针对商贸企业的批发.零售管理设计的软硬件集成一体化的移动POS开单扫描解决方案--"移动开单掌上POS".它集后台管理软件.商品价格.库存等信息查询,店铺.展销会开单,移动捡货配送 ...

  5. MVC5 网站开发实践 2、后台管理

    目录 MVC5 网站开发实践 概述 MVC5 网站开发实践 1.建立项目   从这一部分开始做后台管理,首先是基本框架的 一.Data项目 1.项目添加EntityFramework引用 在Data项 ...

  6. 学用MVC4做网站六:后台管理(续)

    关于后台的说明: 后台将会用easyui + ajax模式. 这里涉及两个问题,一个是使用easyui如何在前台验证模型的问题,另一个是ajax提交后返回数据. 一.Easyui验证 前台验证采用ea ...

  7. php相册功能实现(包含php图片上传,后台管理,浏览和删除)教程例子

    相册功能实现(包含php图片上传,后台管理,浏览和删除)教程例子包括五个部分: 一.相册首页 <html> <head> <meta charset="utf- ...

  8. 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现

    本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...

  9. yii2-basic后台管理功能开发之三:自定义GridView列显示

    在第二篇 yii2-basic后台管理功能开发之二:创建CRUD增删改查 中,我们利用gii工具生成的结果一般并不是我们想要的结果. 我们需要根据自己的需求自定义列显示.我遇到的主要是一下变更: 时间 ...

随机推荐

  1. centos 系统安装基本步骤,面试必考

    1.调整开机媒体,通常为cd或者dvd,也可以是u盘. 2.选择安装模式,是否需要图形化 3.语系及键盘语系选择 4.软件选择 5.磁盘分区操作,主+扩展分区最多4个.逻辑分区在扩展分区下建立 6.时 ...

  2. 关于jquery的click()方法

    昨天,有个同事研究了以下jqury的click()方法,代码如下: <!DOCTYPE html> <html> <head> <meta charset=& ...

  3. SEGGER RTT STOP/SLEEP 模式下使用

    1.问题详述, M3/M4内核在sleep 或者 STOP模式 下,内核是不工作的,因此需要 以下 几步操作 第一步: 开启 低功耗模式下,debug 的连接 DBGMCU_Config(DBGMCU ...

  4. 02_Docker在CentOS 6和CentOS 7下的安装

    CentOS 7 环境下安装docker 安装Docker 检查系统内核是否高于Linux3.10版本 uname -r 使用root权限操作,确保yum包是最新版本 sudo yum update ...

  5. 记录一下安装 mysql 的踩坑之路

    坑点: 1.旧的mysql没有删除干净.在安装mysql的时候,没有注意到,在输入 “mysqld install” 指令时跳出来 exits,存在于另一个文件夹之中,这影响了后来的很多操作,包括ro ...

  6. 基于R语言的结构方程:lavaan简明教程 [中文翻译版]

    lavaan简明教程 [中文翻译版] 译者注:此文档原作者为比利时Ghent大学的Yves Rosseel博士,lavaan亦为其开发,完全开源.免费.我在学习的时候顺手翻译了一下,向Yves的开源精 ...

  7. 2017-2018-1 20155209 实现mypwd

    2017-2018-1 20155209 实现mypwd 1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 3 实现mypwd 4 测试mypwd 首先使用 ...

  8. WPF之ListView使用WrapPanel

    原文:WPF之ListView使用WrapPanel 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/jiuzaizuotian2014/articl ...

  9. 【转载】COM 组件设计与应用(十三)——事件和通知(VC6.0)

    原文:http://vckbase.com/index.php/wv/1243.html 一.前言 我的 COM 组件运行时产生一个窗口,当用户双击该窗口的时候,我需要通知调用者: 我的 COM 组件 ...

  10. Codeforces Round #511 Div.1 A Div.2 C

    嗯切一题走人很开心. gzy-50分比我还惨. 题意:有n个数,去掉尽量少的数使得剩下数的gcd变大. 首先把这n个数都除以gcd,就变成了去掉尽量少的数使得gcd不等于1. 可以枚举一个质数,然后统 ...