码迷,mamicode.com
首页 > 其他好文 > 详细

Django-admin

时间:2018-08-27 21:52:57      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:利用   href   xxxxx   play   hierarchy   type   快速   meta   源码   

一,admin组件使用

Django 提供了基于 web 的管理工具。

Django 自动管理工具是 django.contrib 的一部分。你可以在项目的 settings.py 中的 INSTALLED_APPS 看到它:

INSTALLED_APPS = [
    django.contrib.admin,
    django.contrib.auth,
    django.contrib.contenttypes,
    django.contrib.sessions,
    django.contrib.messages,
    django.contrib.staticfiles,
    app01.apps.App01Config,
]

django.contrib是一套庞大的功能集,它是Django基本代码的组成部分。

激活管理工具

通常我们在生成项目时会在 urls.py 中自动设置好,

from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r^admin/, admin.site.urls),
]

当这一切都配置好后,Django 管理工具就可以运行了。

使用管理工具

启动开发服务器,然后在浏览器中访问 http://127.0.0.1:8000/admin/,得到登陆界面,你可以通过命令 python manage.py createsuperuser 来创建超级用户。

为了让 admin 界面管理某个数据模型,我们需要先注册该数据模型到 admin

技术分享图片
from django.db import models
# Create your models here.


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)

    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.CharField(max_length=11)
    addr = models.CharField(max_length=64)


class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # 与Publish建立一对多的关系,外键字段建立在多的一方
    publish = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
    authors = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title
models.py

admin的定制

在admin.py中只需要将Mode中的某个类注册,即可在Admin中实现增删改查的功能,如:

admin.site.register(models.Book)

但是,这种方式比较简单,如果想要进行更多的定制操作,需要利用ModelAdmin进行操作,如:

方式一:

from django.contrib import admin

# Register your models here.

from app01 import models


class BookConfig(admin.ModelAdmin):
    # admin中查询页面展示的效果,都展示那几个字段,注意下面的list_display中不能加多对多字段
    # (django不确定要采用那种分割符,把多对多的关系展示出来,所以就没写)
    list_display = ["title", "price", "publish"]
    # 那个字段可以跳转到该对象的编辑页面,不写默认是第一个字段
    list_display_links = ["title", "price"]
    # 按括号里的字段筛选显示,一般选择有一对多关系,和多对多关系的字段才有意义
    list_filter = ["title", "publish", "authors"]
    # 搜索框按照什么去搜素, 多个字段之间搜索是"或"的关系
    search_fields = ["title", "price"]

    # 批量操作,Action
    # 自己定义方法,
    def patch_init(self, request, queryset):
        """
        自定义初始化的批量操作方法
        :param request:
        :param queryset:
        :return:
        """
        queryset.update(price=0)  # 把选中的所有书籍的价格变为0(初始化)
    patch_init.short_description = "价格初始化"  # 显示页面的action的描述
    actions = [patch_init]

admin.site.register(models.Book, BookConfig)
admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)

方式二:

from django.contrib import admin

# Register your models here.

from app01 import models


# 利用装饰器的方式
@admin.register(models.Book)
class BookConfig(admin.ModelAdmin):
    # admin中查询页面展示的效果,都展示那几个字段,注意下面的list_display中不能加多对多字段
    # (django不确定要采用那种分割符,把多对多的关系展示出来,所以就没写)
    list_display = ["title", "price", "publish"]  # 也可以是元组的形式
    # 那个字段可以跳转到该对象的编辑页面,不写默认是第一个字段
    list_display_links = ["title", "price"]
    # 按括号里的字段筛选显示,一般选择有一对多关系,和多对多关系的字段才有意义
    list_filter = ["title", "publish", "authors"]
    # 搜索框按照什么去搜素, 多个字段之间搜索是"或"的关系
    search_fields = ["title", "price"]

    # 批量操作,Action
    # 自己定义方法,
    def patch_init(self, request, queryset):
        """
        自定义初始化的批量操作方法
        :param request:
        :param queryset:
        :return:
        """
        queryset.update(price=0)  # 把选中的所有书籍的价格变为0(初始化)
    patch_init.short_description = "价格初始化"  # 显示页面的action的描述
    actions = [patch_init]


admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)

ModelAdmin中提供了大量的可定制功能,如

 1. list_display,列表时,定制显示的列。

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    list_display = (‘user‘, ‘pwd‘, ‘xxxxx‘)
 
    def xxxxx(self, obj):
        return "xxxxx"

2. list_display_links,列表时,定制列可以点击跳转。

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    list_display = (‘user‘, ‘pwd‘, ‘xxxxx‘)
    list_display_links = (‘pwd‘,)

3. list_filter,列表时,定制右侧快速筛选。

4. list_select_related,列表时,连表查询是否自动select_related

5. list_editable,列表时,可以编辑的列 

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    list_display = (‘user‘, ‘pwd‘,‘ug‘,)
    list_editable = (‘ug‘,)  # 这里的字段必须是list_display中有的字段,而且不能和 list_display_links中的字段重复

5. list_editable,列表时,可以编辑的列 

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    list_display = (‘user‘, ‘pwd‘,‘ug‘,)
    list_editable = (‘ug‘,)

6. search_fields,列表时,模糊搜索的功能

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
     
    search_fields = (‘user‘, ‘pwd‘)

7. date_hierarchy,列表时,对Date和DateTime类型进行搜索

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
 
    date_hierarchy = ‘ctime‘

8  inlines,详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除

class UserInfoInline(admin.StackedInline): # TabularInline
    extra = 0
    model = models.UserInfo
 
 
class GroupAdminMode(admin.ModelAdmin):
    list_display = (id, title,)
    inlines = [UserInfoInline, ]

9 action,列表时,定制action中的操作

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
 
    # 定制Action行为具体方法
    def func(self, request, queryset):
        print(self, request, queryset)
        print(request.POST.getlist(_selected_action))
 
    func.short_description = "中文显示自定义Actions"
    actions = [func, ]
 
    # Action选项都是在页面上方显示
    actions_on_top = True
    # Action选项都是在页面下方显示
    actions_on_bottom = False
 
    # 是否显示选择个数
    actions_selection_counter = True

10 定制HTML模板

add_form_template = None
change_form_template = None
change_list_template = None
delete_confirmation_template = None
delete_selected_confirmation_template = None
object_history_template = None

11 raw_id_fields,详细页面,针对FK和M2M字段变成以Input框形式

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
 
    raw_id_fields = (‘FK字段‘, ‘M2M字段‘,)

12  fields,详细页面时,显示字段的字段

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    fields = (‘user‘,)

13 exclude,详细页面时,排除的字段

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    exclude = (‘user‘,)

14  readonly_fields,详细页面时,只读字段

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    readonly_fields = (‘user‘,)

15 fieldsets,详细页面时,使用fieldsets标签对数据进行分割显示

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    fieldsets = (
        (基本数据, {
            fields: (user, pwd, ctime,)
        }),
        (其他, {
            classes: (collapse, wide, extrapretty),  # ‘collapse‘,‘wide‘, ‘extrapretty‘
            fields: (user, pwd),
        }),
    )

16 详细页面时,M2M显示时,数据移动选择(方向:上下和左右)

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)

17 ordering,列表时,数据排序规则

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    ordering = (‘-id‘,)
    或
    def get_ordering(self, request):
        return [‘-id‘, ]

18. radio_fields,详细页面时,使用radio显示选项(FK默认使用select)

radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL

19 form = ModelForm,用于定制用户请求时候表单验证

from app01 import models
from django.forms import ModelForm
from django.forms import fields
 
 
class MyForm(ModelForm):
    others = fields.CharField()
 
    class Meta:
        model = models = models.UserInfo
        fields = "__all__"
 
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
 
    form = MyForm

20 empty_value_display = "列数据为空时,显示默认值"

@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
    empty_value_display = "列数据为空时,默认显示"
 
    list_display = (user,pwd,up)
 
    def up(self,obj):
        return obj.user
    up.empty_value_display = "指定列数据为空时,默认显示"

二,admin源码分析

单例模式点我

admin执行流程

1,启动

django启动之后,首先找到settings.py中的install_app,

# Application definition

INSTALLED_APPS = [
    django.contrib.admin,
    django.contrib.auth,
    django.contrib.contenttypes,
    django.contrib.sessions,
    django.contrib.messages,
    django.contrib.staticfiles,
    app01.apps.App01Config,
]

然后循环加载执行所有已经注册的app中的admin.py文件,(加载每一个app下的admin.py文件)

from django.contrib.admin.sites import AdminSite, site

def autodiscover():  # 源码
    autodiscover_modules(admin, register_to=site)

2,注册

首先我们可以通过

  from django.contrib.admin.sites import AdminSite, site

找到sites.py

import  ......

all_sites = WeakSet()


class AlreadyRegistered(Exception):
    pass


class NotRegistered(Exception):
    pass


class AdminSite(object):
    # 此处省略n行代码
     def register(self, model_or_iterable, admin_class=None, **options):
        """
        Registers the given model(s) with the given admin class.

        The model(s) should be Model classes, not instances.

        If an admin class isn‘t given, it will use ModelAdmin (the default
        admin options). If keyword arguments are given -- e.g., list_display --
        they‘ll be applied as options to the admin class.

        If a model is already registered, this will raise AlreadyRegistered.

        If a model is abstract, this will raise ImproperlyConfigured.
        """
        if not admin_class:
            admin_class = ModelAdmin

        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]
        for model in model_or_iterable:
            if model._meta.abstract:
                raise ImproperlyConfigured(
                    The model %s is abstract, so it cannot be registered with admin. % model.__name__
                )

            if model in self._registry:
                raise AlreadyRegistered(The model %s is already registered % model.__name__)

            # Ignore the registration if the model has been
            # swapped out.
            if not model._meta.swapped:
                # If we got **options then dynamically construct a subclass of
                # admin_class with those **options.
                if options:
                    # For reasons I don‘t quite understand, without a __module__
                    # the created class appears to "live" in the wrong place,
                    # which causes issues later on.
                    options[__module__] = __name__
                    admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)

                # Instantiate the admin class to save in the registry
                self._registry[model] = admin_class(model, self)

# 此处省略n行代码
       pass

# This global object represents the default admin site, for the common case.
# You can instantiate AdminSite in your own code to create a custom admin site.
site = AdminSite()

可以看到,这个sites.py中有一个类叫做AdminSite,里面有register方法,最重要的是该sites.py文件中的site是AdminSite()这个类实例化得到的一个对象,也就是说我们不管在拿导入这个sites.py包时,使用的site都是同一个AdminSite()的对象(即Python 的模块就是天然的单例模式,导入包的第一次是执行该py文件,第二次再导入,都是使用第一次导入时生成的.pyc文件中的内容),

我们注册时是这样注册的:

admin.site.register(models.Book, BookConfig)
admin.site.register(models.Publish)

这里的admin.site中的site就是上面的单例site,再看其register方法,(在实例化site的类中找)

register方法中需要2个参数:model_or_iterable, admin_class=None,

按照我们传入的参数models.Book, BookConfig,也就是models.Book对应model_or_iterable, BookConfig对应admin_class;

在register方法中,我们可以看到,如果没有传入第二个参数,就使用默认的ModelAdmin;

if not admin_class:
    admin_class = ModelAdmin  # 这也就说明了我们在写自己的规范类BookConfig时,要继承ModelAdmin

如果传入了第二个参数,就是用我们自己的BookConfig,

最后执行:

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

这个_registry就是这个类中定义的一个字典

技术分享图片

最后将所有的我们写的注册的类都加到这个字典中,我们可以手动打印这个字典验证:

技术分享图片

可以看到,我一共注册了4个,加上django自带的两张表(Group, User),一共6个键值对;

 如果有多个app,按照注册顺序,都是添加在该键值对中,因为单例模式。

到这里,注册over!

 

 

 

 

Django-admin

标签:利用   href   xxxxx   play   hierarchy   type   快速   meta   源码   

原文地址:https://www.cnblogs.com/glh-ty/p/9544020.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!