Xadmin

一  启动

1.创建一个Xadmin的app

2.在每个APP中创建Xadmin.py文件

3.在Xadmin中找到apps.py,如下图:

        

          下面的框中内容代表,加载项目时,自动运行整个项目中所有Xadmin.py

二 注册

1.把Xadmin当做组件可以拿到别的应用去用,所以把源码写到Xadmin的app中

  在Xadmin中创建一个service包,包中创建一个Xadmin.py

class ModelXadmin():
    def __init__(self,model,site):
        self.model = model
        self.site = site


class XadminSite(object):
    def __init__(self, name='admin'):
        self._registry = {}
    def register(self, model, admin_class=None, **options):
            if not admin_class:  #如果注册时不用自定义样式类,默认用ModelXadmin
                     admin_class = ModelXadmin
            self._registry[model] = admin_class(model, self)#用自己定制的样式类

            
site=XadminSite() #实例化一个单例对象site 
                  #每次注册都不会重新加载,都会存入_registry的字典中

可以在其他APP中的Xadmin中引入单例对象 进行注册:

from Xadmin.service.Xadmin import site,ModelXadmin
    from app01.models import *  #引用app01下的 数据表
    site.register(表名)
    site.register(Book)
    site.register(Auth)

三 url分发

把所有构建url分发的函数 封装在ModelXadmin类中,在urls.py中就可以用url(r'^Xadmin/', site.urls)

from django.conf.urls import url
from django.shortcuts import HttpResponse,render,redirect
class ModelXadmin(object):
    def __init__(self,model,site):

        self.model=model
        self.site=site

    def list_view(self, request):
        print("self.model",self.model)

        data_list=self.model.objects.all()
        print("data_list",data_list)
        return render(request, 'list_view.html',{"data_list":data_list})

    def add_view(self, request):
        return render(request, 'add_view.html')

    def change_view(self, request, id):
        return render(request, 'change_view.html')

    def delete_view(self, request, id):
        return render(request, 'delete_view.html')

    def get_urls2(self):
        temp = []

        temp.append(url(r"^$", self.list_view))
        temp.append(url(r"^add/$", self.add_view))
        temp.append(url(r"^(d+)/change/$", self.change_view))
        temp.append(url(r"^(d+)/delete/$", self.delete_view))

        return temp

    @property
    def urls2(self):
        return self.get_urls2(), None, None


class XadminSite(object):
    def __init__(self, name='admin'):
        self._registry = {}


    def get_urls(self):

        print(self._registry)  # {Book:modelAdmin(Book),.......}

        temp = []
        for model, admin_class_obj in self._registry.items():
            app_name = model._meta.app_label
            model_name = model._meta.model_name

            temp.append(url(r'^{0}/{1}/'.format(app_name, model_name), admin_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 = ModelXadmin

        self._registry[model] = admin_class(model, self) # {Book:ModelAdmin(Book),Publish:ModelAdmin(Publish)}

site=XadminSite()
server/Xadmin.py

如何在不同url的相同视图函数中,展示不同的数据

1  先创建增删改查的html文件,在视图中renderhtml页面

2  注册的时候如果不传自己的样式,所有模型表都默认 用的admim_class样式类 

  把二级分发以及对应的增删改查视图函数,从XadminSite中拿到ModelXadmin(配置类)类中

  for model , admin_class_obj in self._registry.items()  中   admin_class_obj 就是ModelXadmin的实例对象,

  在XadminSite中拿二级分发就可以 admin_class_obj.urls2,这样就多了一个self.model   

  访问哪张表,self.model就是哪张表模型,就能拿到对应表的数据,实现相同的模板,渲染不同数据

  在视图函数中拿到当前表数据(如图):

  

 五  增删改查的 页面设计

额外知识点:

在后端把标签传给前端,前端会做转义,变成字符串的形式,无法渲染页面,需要用:

from django.utils.safestring import  mark_safe
mark_safe("<a href=''>编辑</a>")

由于不知道要渲染的数据是谁,所以不能 向之前一样,在模板里渲染

1     需要把数据做成列表套列表的形式:[["title",price],["python红宝书",23],["python宝典",38]]

  需要在后端循环当前访问的表(self.model.objects.all())

  先在app下的Xadmin中注册的时候,把想展示的字段数据放在list_display 中:list_display=["nid","title","publish"],然后在ModelXadmin中创建一个list_display=[]

  如果注册的时候,没有自定义样式类,list_display会为空,所以想要默认显示,需要在ModelXadmin中让list_display=[__str__]

def list_view(self, request)中的代码(要展示的数据):


  data_list = self.model.objects.all() #当前访问的页面所有数据 new_data_list=[] for obj in data_list: # data_list [book_obj,book_obj2,...] temp=[] for field in self.list_display: # ['title', 'prcie'] 注册时列表中添加所要展示的字段,如果想在列表添加函数,需要注册时,自定义样式类时,在类中写函数 if isinstance(field,str): #list_display中可能存放函数,所以需要先判断一下 val=getattr(obj,field) #拿到的field是字符串,所以需要用getattr代替obj.field(对象.属性) else: val=field(self,obj) #拿到的是函数(函数中可以返回a标签,编辑,删除),拿到返回值 temp.append(val) #把函数的返回值或者标的字段添加到temp中 new_data_list.append(temp) #把temp列表 放在 new_data_list列表中,做成列表套列表的形式

def list_view(self, request)中的代码(要展示的表头):

返回的一个列表就可以了,虽然list_display存的是每一个字段名,可以循环出来作为表头,但是这样无法修改成中文字段,所以,在创建表字段加一个verbose_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)

如何显示中文:

  创建表 中的每一个字段,其实都是一个实例对象,拿到当前字段的实例对象用:

  

  obj= 表名._meta.get_filed(字段)

  然后:    obj.verbose_name   就可以拿到中文名

# 处理表头
        #header_list=["ID","书籍名称","出版社"]
        header_list=[]
        for field in self.list_display: # [check,"nid","title","publish",edit,delete]
            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)  #  获取表头,传is_header=True 证明拿到的是表头,不需要写修改 删除

            header_list.append(val)

当前查看表:

编辑和删除都是空的,那么,如何点击编辑删除,跳转到当前数据的指定页面:

1  在视图中,执行列表中的函数时,把obj,传进去:

 else:
                    val=field(self,obj)     #拿到的是函数(函数中可以返回a标签,编辑,删除),拿到返回值

2  自定义样式类就可以拿到当前对象,拼接url:

class BookConfig(ModelXadmin):
    def edit(self,obj=None,is_header=False):   #obj=None  调用时,可传可不传。is_header=False,如果传了,证明是表头,不传走下面,返回编辑的a标签
        if is_header:
            return "操作"
        # 反向解析:url
        return mark_safe("<a href='%s/change/'>编辑</a>"%obj.pk)

  上面这种方式就可以拼接成想要的url,该方法不好,下面用反向解析找到url:

    定义视图函数的每一个url路径的时候,起一个name别名

原文地址:https://www.cnblogs.com/pygg/p/9146906.html