一、url的分发练习

from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import  HttpResponse
def index(request):
    return HttpResponse("首页")
    
    
def add(request):                         #add视图函数
    return HttpResponse("add")
def list_view(request):                  #list_view视图函数
    return HttpResponse("list_view")
def change(request,id):                  #change视图函数
    return HttpResponse("change")
def delete(request,id):                  #delete视图函数
    return HttpResponse("delete")
    
    
def get_urls2():                        #url的二级分发函数
    temp=[
        url("^add/$",add),
        url("^$",list_view),
        url("^(\d+)/change/$",change),
        url("^(\d+)/delete/$",delete),
    ]
    return temp
    
def get_urls():
    temp=[]
    for model,model_class_obj in admin.site._registry.items(): # 模型类:该模型类的配置类对象 {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....}
          app_name=model._meta.app_label                      #得到应用名
          model_name=model._meta.model_name
          temp.append(url(r"%s/%s/"%(app_name,model_name),(get_urls2(),None,None)))   #url做分发,后面跟元组,元组第一项为一个列表
    return  temp
    
from stark.service.sites import site
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^stark",(get_urls(),None,None))
]


二、实现stark组件


app01应用的models.py文件:

from django.db import models
class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name
class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name
class Book(models.Model):
    nid = models.AutoField(primary_key=True,verbose_name="编号")
    title = models.CharField( max_length=32,verbose_name="名称")
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
    # 与Publish建立一对多的关系,外键字段建立在多的一方
    publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
    authors=models.ManyToManyField(to='Author',)
    def __str__(self):
        return self.title
        
        
#执行下面python语句生成相关表(数据迁移)
# python3 manage.py makemigrations
# python3 manage.py migrate


项目下的settings.py文件设置:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    "app02.apps.App02Config",
    "stark.apps.StarkConfig",
]


STATIC_URL = '/static/'
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,"static")
]


项目的urls.py文件:

from django.conf.urls import url
from django.contrib import admin
from stark.service.sites import site
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^stark/', site.urls),               #模拟admin的实现方式,在stark目录后面进行分发
]


app01应用的stark.py文件对app01的应用表进行注册:


from stark.service.sites import site,ModelStark
from app01.models import Book
from app01.models import Publish
from app01.models import Author
class BookConfig(ModelStark):
    # def display_authors(self, obj=None,is_header=False):     #显示多对多字段,单独定义函数实现方式
    #
    #     if is_header:
    #         return "作者"
    #     s=[]
    #     for author in obj.authors.all():
    #         s.append(author.name)
    #
    #     return " ".join(s)
    list_display = ["nid","title","price","publish","authors",]
    # list_display = ["nid","title","price","publish",display_authors]
site.register(Book,BookConfig)
site.register(Publish)
site.register(Author)


项目下的stark目录下apps.py定义执行各个应用的stark.py:


from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules
class StarkConfig(AppConfig):
    name = 'stark'
    def ready(self):
        autodiscover_modules('stark')      # 执行每一个app下的stark.py


项目下的stark目录下service目录下sites.py定义对用户访问url的分发:

from django.conf.urls import url
from django.shortcuts import HttpResponse, render
from django.utils.safestring import mark_safe
class ModelStark():                    #将增,删,改,查写到ModelStark类中,这样谁调用类中的功能,self.model就是用户访问的表
    list_display = ["__str__", ]
    def __init__(self, model, site):
        self.model = model
        self.site = site
    def edit(self, obj=None, is_header=False):
        if is_header:
            return "操作"                                                   #表头返回 "操作"
        return mark_safe("编辑" % obj.pk)        #mark_safe会识别返回的html标签
    def delete(self, obj=None, is_header=False):
        if is_header:
            return "操作"
        return mark_safe("删除" % obj.pk)
    def checkbox(self, obj=None, is_header=False):
        if is_header:
            return "选择"
        return mark_safe("" % obj.pk)        #在对应位置显示多选框
    def add(self, request):
        return HttpResponse("add")
    def new_list_display(self):                 #新的显示样式,这样所有表的显示都有多选框,编辑和删除操作
        temp = []
        temp.append(ModelStark.checkbox)
        temp.extend(self.list_display)
        temp.append(ModelStark.edit)
        temp.append(ModelStark.delete)
        return temp
    def list_view(self, request):
        print(self.model)
        data_list = self.model.objects.all()
        print("list_display", self.list_display)  # ["nid","title","price",edit]
        # 处理表头
        header_list = []
        for field in self.new_list_display():
            if isinstance(field, str):                              #判断field是字符串类型
                if field == "__str__":                            #字段是__str__
                    val = self.model._meta.model_name.upper()        #表头显示表名的大写字母
                else:
                    field_obj = self.model._meta.get_field(field)
                    val = field_obj.verbose_name                      #得到字段的verbose_name,定义后可以显示中文
            else:
                val = field(self, is_header=True)                  #field是函数,执行函数
            header_list.append(val)
        # 处理表单数据
        new_data_list = []
        for obj in data_list:
            temp = []
            for field in self.new_list_display():  # ["nid","title","price","authors",edit]    ['__str__']     ["title","price"]
                if isinstance(field, str):
                    try:
                        from django.db.models.fields.related import ManyToManyField
                        field_obj = self.model._meta.get_field(field)          #得到field的字段对象
                        if isinstance(field_obj, ManyToManyField):            #判断是多对多关系的字段
                            l = []
                            for i in getattr(obj, field).all():             #.all()得到所有的对象,否则none
                                l.append(str(i))
                            val = ",".join(l)
                        else:
                            val = getattr(obj, field)
                            print("val", val)
                    except Exception as e:
                        val = getattr(obj, field)                      #反射,取到字段名
                else:
                    val = field(self, obj)
                temp.append(val)
            new_data_list.append(temp)
        return render(request, "list_view.html", locals())
    def change(self, request, id):
        return HttpResponse("change")
    def delete_view(self, request, id):
        return HttpResponse("delete_view")
    def get_urls2(self):
        temp = [
            url("^add/$", self.add),
            url("^$", self.list_view),
            url("^(\d+)/change/$", self.change),
            url("^(\d+)/delete/$", self.delete_view),
        ]
        return temp
    @property
    def urls2(self):
        return self.get_urls2(), None, None
        
        
class StarkSite():
    def __init__(self, ):
        self._registry = {}
    # 一级分发
    def get_urls(self):
        temp = []
        for model, model_class_obj in self._registry.items():  # {Book:ModelAdmin(Book),Publish:ModelAdmn(Publish),....}
            app_name = model._meta.app_label
            model_name = model._meta.model_name
            temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2))  #接着二级分发
        return temp
    @property
    def urls(self):
        return self.get_urls(), None, None
    def register(self, model, admin_class=None, **options):
        if not admin_class:
            admin_class = ModelStark
        self._registry[model] = admin_class(model, self)
        
        
site = StarkSite()


list_view.html页面:




    
    Title
    


查看数据

    
        
                                                                              {% for foo in header_list %}                           {{ foo }}                           {% endfor %}                                                                               {% for new_data in new_data_list %}                                                 {% for foo in new_data %}                          {{ foo }}                          {% endfor %}                                              {% endfor %}                                       
    


三、显示多对多字段的另一种方法


stark.py注册表时自定义函数:

class BookConfig(ModelStark):
    def display_authors(self, obj=None,is_header=False):     #显示多对多字段
        if is_header:
            return "作者"
        s=[]
        for author in obj.authors.all():
            s.append(author.name)
        return " ".join(s)
    list_display = ["nid","title","price","publish",display_authors]


sites.py里面的ModelStark类定义的list_view

def list_view(self, request):
    print(self.model)
    data_list = self.model.objects.all()
    print("list_display", self.list_display)  #  ["nid","title","price",edit]
    # 处理表头
    # header_list=["ID","名称","价格"]
    header_list=[]
    for field in self.new_list_display():
        if isinstance(field,str):
            if field=="__str__":
                val=self.model._meta.model_name.upper()
            else:
                field_obj=self.model._meta.get_field(field)
                val=field_obj.verbose_name
        else:
            val=field(self,is_header=True)
        header_list.append(val)
    # 处理表单数据
    new_data_list = []
    for obj in data_list:
        temp = []
        for field in self.new_list_display():  #   ["nid","title","price","authors",edit]    ['__str__']     ["title","price"]
            if isinstance(field,str):
                val = getattr(obj, field)
            else:
                val=field(self,obj)
            temp.append(val)
        new_data_list.append(temp)

页面显示效果图:

基于Django-admin实现stark组件_第1张图片


四、stark组件自定义功能设置

app01应用下的stark.py文件:

from stark.service.sites import site,ModelStark
from app01.models import Book
from app01.models import Publish
from app01.models import Author
class BookConfig(ModelStark):
    def display_authors(self, obj=None,is_header=False):
        if is_header:
            return "作者"
        s=[]
        for author in obj.authors.all():
            s.append(author.name)
        return " ".join(s)
    list_display = ["nid","title","price","publish","authors",]   #自定义显示的字段
    
    search_fields=["title","price"]                                 #搜索依据的字段
    
    def patch_init(self,selected_pk):
        print("selected_pk",selected_pk)
        ret=self.model.objects.filter(pk__in=selected_pk).update(price=0)
        print("====>",ret)
    patch_init.desc="批量初始化"
    def patch_delete(self,selected_pk):
        print("selected_pk",selected_pk)
        ret=self.model.objects.filter(pk__in=selected_pk).delete()
        print("====>",ret)
    patch_delete.desc="批量删除"
    actions=[patch_init,patch_delete]                               #定义批量操作
    
site.register(Book,BookConfig)
site.register(Publish)
site.register(Author)


stark组件下service目录sites.py文件进行完善:

from django.conf.urls import url
from django.shortcuts import HttpResponse, render, redirect
from django.utils.safestring import mark_safe
from django.urls import reverse
class Show_List(object):
    def __init__(self, config, data_list):
        self.config = config
        self.data_list = data_list
        
    def get_header(self):
        # 处理表头
        # header_list=["ID","名称","价格"]
        header_list = []
        for field in self.config.new_list_display():
            if isinstance(field, str):
                if field == "__str__":
                    val = self.config.model._meta.model_name.upper()
                else:
                    field_obj = self.config.model._meta.get_field(field)
                    val = field_obj.verbose_name
            else:
                val = field(self.config, is_header=True)
            header_list.append(val)
        return header_list
        
    def get_body(self):
        # 处理表单数据
        new_data_list = []
        for obj in self.data_list:
            temp = []
            for field in self.config.new_list_display():  # ["nid","title","price","authors",edit]    ['__str__']     ["title","price"]
                if isinstance(field, str):
                    try:
                        from django.db.models.fields.related import ManyToManyField
                        field_obj = self.config.model._meta.get_field(field)
                        if isinstance(field_obj, ManyToManyField):
                            l = []
                            for i in getattr(obj, field).all():
                                l.append(str(i))
                            val = ",".join(l)
                        else:
                            val = getattr(obj, field)
                            print("val", val)
                    except Exception as e:
                        val = getattr(obj, field)
                else:
                    val = field(self.config, obj)
                temp.append(val)
            new_data_list.append(temp)
        return new_data_list
        
    def get_new_actions(self):
        action_list = []
        for i in self.config.actions:  # [patch_init,]
            action_list.append({
                "desc": i.desc,
                "name": i.__name__,
            })
        return action_list
        
class ModelStark():  # 功能的样式显示类
    list_display = ["__str__", ]
    search_fields = []
    actions = []
    def __init__(self, model, site):
        self.model = model
        self.site = site
        
    def edit(self, obj=None, is_header=False):
        if is_header:
            return "操作"
        return mark_safe("编辑" % obj.pk)
        
    def delete(self, obj=None, is_header=False):
        if is_header:
            return "操作"
        return mark_safe("删除" % obj.pk)
        
    def checkbox(self, obj=None, is_header=False):
        if is_header:
            return "选择"
        return mark_safe("" % obj.pk)
        
    def get_list_url(self):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_list" % (app_label, model_name))
        return _url
        
    def new_list_display(self):
        temp = []
        temp.append(ModelStark.checkbox)
        temp.extend(self.list_display)
        temp.append(ModelStark.edit)
        temp.append(ModelStark.delete)
        return temp
        
    def get_search_condition(self, request):        #定义搜索查找函数
        from django.db.models import Q
        search_condition = Q()
        val = request.GET.get("q")
        if val:
            search_condition.connector = "or"        #设置搜索依据的字段是或者的关系,即满足一个字段的查找结果就可以
            for field in self.search_fields:
                search_condition.children.append((field + "__contains", val))  #搜索的字符串进行模糊匹配
        return search_condition
        
    def list_view(self, request):
        if request.method == "POST":
            action = request.POST.get("action")
            selected_pk = request.POST.getlist("selected_pk")
            action = getattr(self, action)
            action(selected_pk)
        search_condition = self.get_search_condition(request)
        data_list = self.model.objects.all().filter(search_condition)
        print("list_display", self.list_display)  # ["nid","title","price",edit]
        sl = Show_List(self, data_list)
        return render(request, "list_view.html", locals())
        
    def get_mdoelForm(self):
        from django.forms import ModelForm
        class DemoModelForm(ModelForm):
            class Meta:
                model = self.model
                fields = "__all__"
        return DemoModelForm
        
    def add(self, request):                         #定义添加页面的函数
        if request.method == "POST":
            form = self.get_mdoelForm()(request.POST)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
            else:
                return render(request, "add.html", locals())
        form = form = self.get_mdoelForm()()
        return render(request, "add.html", locals())
        
    def change(self, request, id):                   #定义编辑函数
        obj = self.model.objects.filter(pk=id).first()
        if request.method == "POST":
            form = self.get_mdoelForm()(request.POST, instance=obj)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
        form = self.get_mdoelForm()(instance=obj)
        return render(request, "change.html", locals())
        
    def delete_view(self, request, id):
        if request.method == "POST":
            self.model.objects.get(pk=id).delete()
            return redirect(self.get_list_url())
        url = self.get_list_url()
        return render(request, "delete.html", locals())
        
    def get_urls2(self):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp = [
            url("^add/$", self.add, name="%s_%s_add" % (app_label, model_name)),
            url("^$", self.list_view, name="%s_%s_list" % (app_label, model_name)),
            url("^(\d+)/change/$", self.change, name="%s_%s_change" % (app_label, model_name)),
            url("^(\d+)/delete/$", self.delete_view, name="%s_%s_delete" % (app_label, model_name)),
        ]
        return temp
    @property
    
    def urls2(self):
        return self.get_urls2(), None, None
        
class StarkSite():
    def __init__(self, ):
        self._registry = {}
    # 一级分发
    def get_urls(self):
        temp = []
        for model, model_class_obj in self._registry.items():
            app_name = model._meta.app_label
            model_name = model._meta.model_name
            temp.append(url(r"%s/%s/" % (app_name, model_name), model_class_obj.urls2))
        return temp
    @property
    def urls(self):
        return self.get_urls(), None, None
        
    def register(self, model, admin_class=None, **options):
        if not admin_class:
            admin_class = ModelStark
        self._registry[model] = admin_class(model, self)
        
site = StarkSite()


templates模板

form.html页面:

    
                                      {% csrf_token %}                 {% for field in form %}                     
                        {{ field.label }}                         {{ field }} {{ field.errors.0 }}                     
                {% endfor %}                                       
    


add.html添加页面:




    
    Title
    
    


添加页面

{% include 'form.html' %}


change.html修改页面:





    
    Title
    
    


编辑页面

{% include 'form.html' %}


delete.html删除页面:




    
    Title
    


删除页面

    {% csrf_token %}          取消


list_view.html显示页面:




    
    Title
    
    


查看数据

添加数据
    
        
                                              search                                           {% csrf_token %}                                         {% for action_dict in sl.get_new_actions %}                            {{ action_dict.desc }}                        {% endfor %}                                  Go                                                                                    {% for foo in sl.get_header %}                             {{ foo }}                         {% endfor %}                                                                                    {% for new_data in sl.get_body %}                                                      {% for foo in new_data %}                                 {{ foo }}                             {% endfor %}                                              {% endfor %}                                                            
    


页面效果图:

基于Django-admin实现stark组件_第2张图片

基于Django-admin实现stark组件_第3张图片

基于Django-admin实现stark组件_第4张图片

基于Django-admin实现stark组件_第5张图片