django中的admin组件之自定义组件

内容回顾:

一 admin的使用

app01的admin.py文件:
         
         class BookConfig(admin.ModelAdmin):
               list_display=[]
               list_display_links=[]
               list_filter=[]
               search_fields=[]
               
               def patch(self,request,queryset):
                   pass
               patch.short_desc=""
               actions=[patch,]
                   
               
         admin.site.register(Book,BookConfig)
        
        
二 admin的源码解析
    1 启动
      加载settings中install_app
      from django.contrib import admin
      autodiscover_modules(‘admin‘)
      
    2 注册
        源码:django.contrib.admin.sites模块
        class AdminSite(object):
              
                  def __init__(self):
                        self._registry = {}
              
                  def register(self,model,admin_class=None):
                       # 设置配置类
                       if not admin_class:
                            admin_class = ModelAdmin
                            
                       self._registry[model] = admin_class(model, self)        
              
              
        site = AdminSite()
        
        每一个app下的admin.py文件:
            from django.contrib import admin
            admin.site.register(Book,BookConfig)
            admin.site.register(Publish)

我们先来说一下admin组件中的第三步,他是如何设计url的

我们之所以能进去admin后台管理界面,是因为有这个url:

我们之前配url时,是这样配置的 url(r"index/",views.index),但是对于admin中,一张表就会对应有多个url,就拿Food表来说:

     针对Food表,url:
                http://127.0.0.1:8000/admin/app02/food/
                http://127.0.0.1:8000/admin/app02/food/add/
                http://127.0.0.1:8000/admin/app02/food/1/change/
                http://127.0.0.1:8000/admin/app02/food/2/delete/

那么admin是怎么实现只配那么一条url呢?其实我们能够想到二级路由,但这里不是二级路由实现的。

我们先来学习一个知识点:

我们这样配url:

‘test/’url后面不写视图函数,后面写一个元祖,元祖里面有三个参数,第一个元祖是一个列表,第二个参数,和第三个参数我们暂时用不到,所以写None。而这个列表中写第二个url,然后我们在app01下的视图函数中写函数aaa。我们可以写的更复杂一点,可以仿照admin中的url写。

url(r‘^stark/‘, ([
                         url(r‘app01/‘, ([
                                             url(r‘food/‘, ([
                                                                url(r‘^$‘, listview),
                                                                url(r‘add/$‘, addview),
                                                                url(r‘(\d+)/change/$‘, changeview),
                                                                url(r‘(\d+)/delete/$‘, delview),
                                                            ], None, None))], None, None))
                     ], None, None))

其实admin后面的admin.site.urls就是实现了这样的url的配置。

这样写肯定也是不对的,也因为我们有很多表,会在不同的app下,当我们点击相应的表会显示相应的app和相应的表的内容,实现一个动态的效果。那么我们怎么来获取相应的app名和表的名呢?

我们在注册的时候不就是往admin.site._registry中添加键值对吗,那个键值对里面刚好有我们需要的。我们可以打印出来看看。

先在modes中写几张表,然后再admin中注册。

def get_urls():
    temp=[]
    print(admin.site._registry)
    return temp

urlpatterns = [
    # url(r‘^admin/‘, admin.site.urls),
    url(r‘^admin/‘,(get_urls(),None,None))  #  这里把元祖中的第一个列表参数写成了一个函数,函数仍然返回的是一个列表,在函数中我们打印admin.site._registry键值对。
]

这是打印的一条结果,他的健是models中的Publish表对象,他的值为admin中自定义写的PublishConfig类对象,那我们怎么取我们想要的东西呢?这里介绍两个方法:

     model_name = model._meta.model_name   # 获取当前model表名
        app_label = model._meta.app_label     # 获取所在app的名字
        print(model_name)
        print(app_label)

既然能够拿到model表的名字和app名,我们就能够实现表的一个动态的增删改查:

接下来我们仿照admin实现一个自定义的增删改查的组件

我们新建一个项目,然后再项目里新建另一个app,起名为stark,作为我们的组件。我们自己写组件的时候,要先理解admin组件是怎么工作的,要清楚admin组件中的流程。不然会很难理解。(别忘了创建stark的app后,将stark添加进settings中的INSTALLED_APPS)。

我们就是要做类似于admin源码里面的那三步,将那三步写进我们自己的stark组件中去。

我们先按照admin的流程来想,我们每个app下面都会有admin.py文件,当我们启动django时,会执行app下的admin.py文件, 这时候是因为执行了源码中的:

def autodiscover():    autodiscover_modules(‘admin‘, register_to=site)

那么我们就想要让他启动时先执行我们自己创建的stark.py文件,也应该执行这句代码。我们先在app01下创建stark.py文件。那这句代码应该放在哪呢?

我们将stark添加进settings中的INSTALLED_APPS,django启动时,会逐个扫描里面的每一个,当他扫描到stark.apps.StarkConfig的时候,会执行StarkConfig,点进去,就会到stark   app下的apps.py文件,意思就是说当他扫描到stark.apps.StarkConfig的时候,会首先执行apps.py文件。所以我们要把这句话放在apps.py文件里。

这样写完之后,启动后就可以先执行app01下的stark.py文件中的内容了。

启动完了之后,就是注册了。

admin在注册的时候其实就是执行了AdminSite的一个单例模式:就是执行了这样一段代码:

class AdminSite(object):

      def __init__(self):
            self._registry = {}

      def register(self,model,admin_class=None):
             # 设置配置类
             if not admin_class:
                admin_class = ModelAdmin

             self._registry[model] = admin_class(model, self)        

 site = AdminSite()

我们要把这段代码单独放在一个模块里,我们也把这个模块的名字叫做sites:

# 默认的配置类class ModelStark(object):
    def __init__(self,model):
        self.model = model
# stark组件的全局类
class AdminSite(object):
    def __init__(self):
        self._registry = {}

    def register(self, model, admin_class=None):
        # 设置配置类
        if not admin_class:
            admin_class = ModelStark

        self._registry[model] = admin_class(model)

site = AdminSite()

这样就可以了。

接下来 ,我们在model里面放几张表。我们之前在admin中注册的时候是这样写的:

from django.contrib import admin

# Register your models here.
from app01.models import Book,Publish,Author,AuthorDetail
# 定义自己的类
class BookConfig(admin.ModelStark):
    #  list_display‘ must not be a ManyToManyField.
    list_display=["title","price","publishDate","publish"]
    list_display_links = ["price","title"]

    list_filter = ["title","publish","authors"]
    search_fields = ["title","price"]

    # 批量操作
    def patch_init(self,request,queryset):
        queryset.update(price=0)

    patch_init.short_description = "价格初始化"

    actions =[patch_init]

admin.site.register(Book,BookConfig)

class PublishConfig(admin.ModelAdmin):
    list_display = ["name","email"]
admin.site.register(Publish,PublishConfig)
admin.site.register(Author)
admin.site.register(AuthorDetail)

也就是说要在我们自己app01下的stark.py下进行注册。就应该这样写:

from stark import sites
from app01 import models

sites.site.register(models.Book)
sites.site.register(models.Publish)
sites.site.register(models.AuthorDetail)
sites.site.register(models.Author)

当然我们也可以添加自己的类:

from stark import sites
from app01 import models

# 定义自己的类
class Bookconfig(sites.ModelStark):
    #  list_display‘ must not be a ManyToManyField.
    list_display = ["title", "price", "publishDate", "publish"]
    list_display_links = ["price", "title"]
    list_filter = ["title", "publish", "authors"]
    search_fields = ["title", "price"]
    # 批量操作
    def patch_init(self, request, queryset):
        queryset.update(price=0)
    patch_init.short_description = "价格初始化"
    actions = [patch_init]
sites.site.register(models.Book,Bookconfig)
sites.site.register(models.Publish)
sites.site.register(models.AuthorDetail)
sites.site.register(models.Author)

这样就注册好了。

这时候我们也可以print(sites.site._registry)看看里面有几个键值对。

接下来就是第三部分,设计url了:

之前我们已经写好了url,但是:

urlpatterns = [
    # url(r‘^admin/‘, admin.site.urls),
    url(r‘^admin/‘,(get_urls(),None,None))
]我们写的这个url和admin中的不一样,我们也希望将自己写的url放进我们写的stark组件中。我们应该这样写:
from stark import sites urlpatterns = [
    url(r‘^stark/‘,sites.site.urls)
]这样写那说明,site的那个实例化类中要有urls的这个方法,只要这个urls方法返回的是([],None,None),接下来我们就要在那个类中添加这个方法:
    def get_urls2(self):
        temp = [
            url(r‘^$‘, listview),
            url(r‘add/$‘, addview),
            url(r‘(\d+)/change/$‘, changeview),
            url(r‘(\d+)/delete/$‘, delview),
        ]
        return temp
    def get_urls(self):
        temp = []
        for model, config_obj in self._registry.items():  # 循环分别打印健和值。
            model_name = model._meta.model_name  # 获取当前model的表名
            app_label = model._meta.app_label  # 获取所在的app名字
            print(model_name)
            print(app_label)
            temp.append(url(r‘%s/%s/‘ % (app_label, model_name), (self.get_urls2(), None, None)))
        return temp
    @property
    def urls(self):
        return self.get_urls(),None,None
在AdminSite()类中添加这些东西,我们觉得这样就成功了,但是一级url的分发(get_urls())和二级url的分发( get_urls2()),是不能放在一个类中的,因为我们的二级url分发是需要访问视图函数的,那么我们怎么能够保证当我们点击书籍的时候就访问书籍的列表访问publish就展示publish的列表,如果我们这样写,就只能进入一个视图函数了。所以二级url的分发不能放在这个类里,那我们把这个二级url的分发放在哪里呢?放在那个配置类里面去

将二级url的分发放在配置类中有什么好处?config_obj是我们的配置类, 可以是默认的配置类也可以是自定义的配置类。在这里我们要明白这个self指的是谁,他指的是当前这个配置类,而这个配置类中有就有参数model。虽然访问的时候都要进相同的视图函数,但是每次访问不同的表时的配置类不一样,所以self就不一样,进入的视图函数也就不一样。

这样了解之后,就可以完善视图函数了:

    def listview(self,request):
        print(self)# 当前访问摩星表的配置类对象
        print(self.model)# 当前访问的模型表
        data_list = self.model.object.all()
        return render(request,‘list.html‘,locals())


 

原文地址:https://www.cnblogs.com/yb635238477/p/9551195.html

时间: 2024-11-06 20:14:14

django中的admin组件之自定义组件的相关文章

django中的admin组件之自定义组件的数据展示以及自定义列

虽然我们基本实现了我们自定义组件stark的功能,接下来就是显示数据了. 今天我们先来写查.先来写表单部分 我们如果需要显示我们自己配置类中的字段,应该怎么做呢? 我们有这样一个想法,将这些数据放在一个列表中,类似这样[['python',122],['linux',110]],然后在页面上依次循环这个列表,取值就行了. self.model.objects.all()中里面有我们需要的对象,self.list_display中有我们需要的字段.所以: def listview(self,req

【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件

博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.com/han1202012/WheelViewDemo.git -- CSDN : http://download.csdn.net/detail/han1202012/8208997 ; 博客总结 : 博文内容 : 本文完整地分析了 WheelView 所有的源码, 包括其适配器类型, 两种回调接

Django中的Admin站点

使用Admin站点 假设我们要设计一个新闻网站,我们需要编写展示给用户的页面,网页上展示的新闻信息是从哪里来的呢?是从数据库中查找到新闻的信息,然后把它展示在页面上.但是我们的网站上的新闻每天都要更新,这就意味着对数据库的增.删.改.查操作,那么我们需要每天写sql语句操作数据库吗? 如果这样的话,是不是非常繁琐,所以我们可以设计一个页面,通过对这个页面的操作来实现对新闻数据库的增删改查操作.那么问题来了,老板说我们需要在建立一个新网站,是不是还要设计一个页面来实现对新网站数据库的增删改查操作,

?微信小程序?--基本组件,事件,自定义组件

水了几篇博客真开心.其实不是真的水,也配图啥的吧 .... 好了, 我要开始认真了哈 跟着我 好好学,明年哥给你取个嫂子! 基本组件 <view>这就类似于我们的 div 很简单吧!</view> <text>简单的文本</text> <image>参数有 src mode(图片的裁剪)</image> 简单的水一下就行了 还有两个viedo(视频) 和 swiper(微信内置的轮播图组件) 都在这个链接里了 点击==点我== 事件(

django中的admin组件之自定义组件的search,actions,list_display_links

上节回顾:                               1 反向解析(reverse)                2 modelForm--->添加和编辑                                        添加:                        class BookModelForm():                             class Meta:                                  

django中的admin组件之自定义组件的增删改查的完善

昨天我们将自定义列放在类我们自定义的Bookconfig配置类内,但是这样就写死了,因为当我们访问publish表的时候应该也有这样的自定义列,所以我们应该将我们的自定义列放在默认的配置表里面.应该怎么做? 当我们的自定义列挪到默认配置类的时候,我们自定义配置类中的list_display就要发生改动, list_display = ["title", "price", "publish",'authors','publishDate',site

Django中的tags,母版和继承,组件,静态文件相关,自定义simpletag和自定义inclusion_tag

Tags for <ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul> for循环可用的一些参数: Variable Description forloop.counter 当前循环的索引值(从1开始) forloop.counter0 当前循环的索引值(从0开始) forloop.revcounter 当前循环的倒序索引值(从1开始) forloop.rev

django中的Admin是如何工作的?

1.寻找app的 admin.py 当服务启动时,Django从`` url.py`` 引导URLconf,然后执行`` admin.autodiscover() 语句. 这个函数遍历INSTALLED_APPS配置,并且寻找相关的 admin.py文件. 如果在指定的app目录下找到admin.py,它就执行其中的代码. url.py----(admin.autodiscover)---->INSTALLED_APP----(寻找安装的app)---->admin.py 2.注册模块显示界面

Django 中使用 logging 配置 logger 自定义日志输出

在使用 django 开发过程中,默认的日志输出是不能满足我们去排查问题的,往往需要自定义的日志输出,帮助我们去排查程序BUG,定位问题原因. 在使用 django 的开发过程中,我使用的是 python 内置日志模块 logginglogging 的详细使用讲解我就不多说了,度娘一抓一大抓:我只记录下我在 django settings 中的 logger 配置.方便以后使用 以下在我在 settings 中定义的 logger:# Custom output log LOGGING = {'