Django内置Admin解析
Django 内置的admin是对于model中对应的数据表进行增删改查提供的组建
一.Django admin的内部依赖:
依赖的app
- django.contrib.auth
- django.contrib.contenttypes
- django.contrib.messages
- django.contrib.sessions
模版:
- django.contrib.auth.context_processors.auth
- django.contrib.messages.context_processors.messages
中间件:
- django.contrib.auth.middleware.AuthenticationMiddleware
- django.contrib.messages.middleware.MessageMiddleware
二:配置路由
- from django.conf.urls import url,include
- from django.contrib import admin
- urlpatterns = [
- url(r'^admin/', admin.site.urls),
- ]
当前配置的路由可以创建一些路由映射关系:
/admin/
/admin/login/
/admin/logout/
/admin/password_change/
/admin/password_change/done/
/admin/app名称/model名称/
/admin/app名称/model名称/add/
/admin/app名称/model名称/ID值/history/
/admin/app名称/model名称/ID值/change/
/admin/app名称/model名称/ID值/delete/
- class AdminSite(object):
- """
- An AdminSite object encapsulates an instance of the Django admin application, ready
- to be hooked in to your URLconf. Models are registered with the AdminSite using the
- register() method, and the get_urls() method can then be used to access Django view
- functions that present a full admin interface for the collection of registered
- models.
- """
- # Text to put at the end of each page's <title>.
- site_title = ugettext_lazy('Django site admin')
- # Text to put in each page's <h1>.
- site_header = ugettext_lazy('Django administration')
- # Text to put at the top of the admin index page.
- index_title = ugettext_lazy('Site administration')
- # URL for the "View site" link at the top of each admin page.
- site_url = '/'
- _empty_value_display = '-'
- login_form = None
- index_template = None
- app_index_template = None
- login_template = None
- logout_template = None
- password_change_template = None
- password_change_done_template = None
- def __init__(self, name='admin'):
- self._registry = {} # model_class class -> admin_class instance
- self.name = name
- self._actions = {'delete_selected': actions.delete_selected}
- self._global_actions = self._actions.copy()
- all_sites.add(self)
- 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)
- def get_urls(self):
- from django.conf.urls import url, include
- # Since this module gets imported in the application's root package,
- # it cannot import models from other applications at the module level,
- # and django.contrib.contenttypes.views imports ContentType.
- from django.contrib.contenttypes import views as contenttype_views
- def wrap(view, cacheable=False):
- def wrapper(*args, **kwargs):
- return self.admin_view(view, cacheable)(*args, **kwargs)
- wrapper.admin_site = self
- return update_wrapper(wrapper, view)
- # Admin-site-wide views.
- urlpatterns = [
- url(r'^$', wrap(self.index), name='index'),
- url(r'^login/$', self.login, name='login'),
- url(r'^logout/$', wrap(self.logout), name='logout'),
- url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
- url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
- name='password_change_done'),
- url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
- url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
- name='view_on_site'),
- ]
- # Add in each model's views, and create a list of valid URLS for the
- # app_index
- valid_app_labels = []
- for model, model_admin in self._registry.items():
- urlpatterns += [
- url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
- ]
- if model._meta.app_label not in valid_app_labels:
- valid_app_labels.append(model._meta.app_label)
- # If there were ModelAdmins registered, we should have a list of app
- # labels for which we need to allow access to the app_index view,
- if valid_app_labels:
- regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
- urlpatterns += [
- url(regex, wrap(self.app_index), name='app_list'),
- ]
- return urlpatterns
- @property
- def urls(self):
- return self.get_urls(), 'admin', self.name
源码摘要参考
- option.py BaseModelAdmin类
- def get_urls(self):
- from django.conf.urls import url
- def wrap(view):
- def wrapper(*args, **kwargs):
- return self.admin_site.admin_view(view)(*args, **kwargs)
- wrapper.model_admin = self
- return update_wrapper(wrapper, view)
- info = self.model._meta.app_label, self.model._meta.model_name
- urlpatterns = [
- url(r'^$', wrap(self.changelist_view), name='%s_%s_changelist' % info),
- url(r'^add/$', wrap(self.add_view), name='%s_%s_add' % info),
- url(r'^(.+)/history/$', wrap(self.history_view), name='%s_%s_history' % info),
- url(r'^(.+)/delete/$', wrap(self.delete_view), name='%s_%s_delete' % info),
- url(r'^(.+)/change/$', wrap(self.change_view), name='%s_%s_change' % info),
- # For backwards compatibility (was the change url before 1.9)
- url(r'^(.+)/$', wrap(RedirectView.as_view(
- pattern_name='%s:%s_%s_change' % ((self.admin_site.name,) + info)
- ))),
- ]
- return urlpatterns
- @property
- def urls(self):
- return self.get_urls()
源码参考2
三:定制admin
在admin.py中只需注册某个类,即可在admin中实现增删改查的功能。
- admin.site.register(UserInfo)
为类定制更多的信息,需为其定制modelAdmin
1.应用方式:
- #方式一:装饰器
- @admin.register(UserInfo)
- class UserAdmin(admin.ModelAdmin):
- list_display = ['name','nickname','email']
- #方式二:参数传入
- # admin.site.register(UserInfo,UserAdmin)
2.定制功能:
list_display,列表时,定制显示的列。
list_display 有四种赋值方式:
- #模型的字段
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('first_name', 'last_name')
- #一个接受对象实例作为参数的可调用对象
- def upper_case_name(obj):
- return ("%s %s" % (obj.first_name, obj.last_name)).upper()
- upper_case_name.short_description = 'Name'
- class PersonAdmin(admin.ModelAdmin):
- list_display = (upper_case_name,)
- #一个表示ModelAdmin 中某个属性的字符串。行为与可调用对象相同
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('upper_case_name',)
- def upper_case_name(self, obj):
- return ("%s %s" % (obj.first_name, obj.last_name)).upper()
- upper_case_name.short_description = 'Name'
- #表示模型中某个属性的字符串。它的行为与可调用对象几乎相同,但这时的self 是模型实例。
- from django.db import models
- from django.contrib import admin
- class Person(models.Model):
- name = models.CharField(max_length=50)
- birthday = models.DateField()
- def decade_born_in(self):
- return self.birthday.strftime('%Y')[:3] + "0's"
- decade_born_in.short_description = 'Birth decade'
- class PersonAdmin(admin.ModelAdmin):
- list_display = ('name', 'decade_born_in')
list_display 数据类型
实例:
- @admin.register(UserInfo)
- class UserAdmin(admin.ModelAdmin):
- list_display = ['name','nickname','email','xxx']
- list_display_links = ('nickname',)
- def xxx(self,obj):
- a = '<a href="www.baidu.com>点击跳转</a>'
- return mark_safe(a)
list_display_links,指定列表显示的哪列可以点击跳转,定制列可以点击跳转。
list_filter 设置激活激活Admin 修改列表页面右侧栏中的过滤器
- #字段名称,其指定的字段应该是BooleanField、CharField、DateField、DateTimeField、#IntegerField、ForeignKey 或ManyToManyField,
- class UserAdmin(admin.ModelAdmin):
- list_filter = ('group','roles')
- #list_filter 中的字段名称也可以使用__ 查找跨关联关系
- list_filter = ('group__title','roles')
- #一个继承自django.contrib.admin.SimpleListFilter 的类,你需要给它提供title 和 parameter_name 属性来重写lookups 和queryset 方法
- from django.contrib import admin
- from app01.models import *
- from django.utils.safestring import mark_safe
- from django.utils.translation import ugettext_lazy as _
- class Ugg(admin.SimpleListFilter):
- title = _('decade born')
- parameter_name = 'xxxxxx'
- def lookups(self, request, model_admin):
- """
- 显示筛选选项
- :param request:
- :param model_admin:
- :return:
- """
- return UserGroup.objects.values_list('id', 'title')
- def queryset(self, request, queryset):
- """
- 点击查询时,进行筛选
- :param request:
- :param queryset:
- :return:
- """
- v = self.value()
- return queryset
- list_filter = ('group',Ugg)
- #一个元组,第一个元素是字段名称,第二个元素是从继承自django.contrib.admin.FieldListFilter 的一个类
- class PersonAdmin(admin.ModelAdmin):
- list_filter = (
- ('is_staff', admin.BooleanFieldListFilter),
- )
list_filter 数据类型
list_select_related,设置list_select_related以告诉Django在检索管理更改列表页面上的对象列表时使用 select_ralated。这可以节省大量的数据库查询。该值应该是布尔值,列表或元组。默认值为False。
- list_select_related = ['group']
list_max_show_all 控制在“显示所有”管理更改列表页面上可以显示的项目数,默认情况下,设置为200。
list_per_page. 设置控制Admin 修改列表页面每页中显示多少项。默认设置为100。
ordering以指定如何在Django管理视图中对对象列表进行排序
- ordering = ['-id', ]. 从大到小
- ordering = ['id', ]. 从小到大
paginator 默认情况下,使用django.core.paginator.Paginator
prepopulated_fields设置为将字段名称映射到其应预先填充的字段的字典:
- prepopulated_fields = {'name':('nickname','email')} #nickname 和email和name的值相同
prepopulated_fields不接受DateTimeField,ForeignKey或ManyToManyField字段。
list_editable指定列表中可以编辑的列
- list_editable = ('name',)
-
search_fields,模糊搜索时列表中的搜索列范围,
- search_fields = ('namer', 'email')
date_hierarchy,列表时,对Date和DateTime类型进行搜索
preserve_filters,详细页面,删除、修改,更新后跳转回列表后,是否保留原搜索条件
save_as = False,详细页面,按钮为“Sava as new” 或 “Sava and add another”
save_as_continue = True,点击保存并继续编辑
save_on_top = False,详细页面,在页面上方是否也显示保存删除等按钮
fields,详细页面时,显示字段的字段
exclude,详细页面时,排除的字段
readonly_fields,详细页面时,只读字段
fieldsets,详细页面时,使用fieldsets标签对数据进行分组显示
- fieldsets = (
- ('基本数据', {
- 'fields': ('name', )
- }),
- ('其他', {
- 'classes': ('collapse', 'wide', 'extrapretty'), # 'collapse','wide', 'extrapretty'
- 'fields': ('email','group',),
- }),
- )
多对多或一对多显示时添加数据移动选择(方向:上下和左右)
- @admin.register(models.UserInfo)
- class UserAdmin(admin.ModelAdmin):
- filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)
inlines,详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除
inlines 关联的类必须继承:StackedInline,且放在外键的类里
- class UserInfoInline(admin.StackedInline): # TabularInline
- extra = 0
- model = UserInfo
- class UserGropuAdmin(admin.ModelAdmin):
- inlines = [UserInfoInline,]
action 定制action中的操作
- def func(self, request, queryset): (必须有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
在整个站点应用该操作:
- from django.contrib import admin
- admin.site.add_action(fund)
为全局ModelAdmin禁用某个操作
- admin.site.disable_action('delete_selected')
为特定的ModelAdmin禁用所有操作ModelAdmin
- class MyModelAdmin(admin.ModelAdmin):
- actions = None
按需启用或禁用操作
- class MyModelAdmin(admin.ModelAdmin):
- ...
- def get_actions(self, request):
- actions = super(MyModelAdmin, self).get_actions(request)
- if request.user.username[0].upper() != 'J':
- if 'delete_selected' in actions:
- del actions['delete_selected']
- return actions
定制HTML模板
Admin模板文件位于contrib/admin/templates/admin 目录中。
为一个特定的app重写admin模板, 需要拷贝django/contrib/admin/templates/admin 目录到你刚才创 建的目录下, 并且修改它们.
- 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
view_on_site,编辑时,是否在页面上显示view on set
- view_on_site = False
- 或
- def view_on_site(self, obj):
- return 'https://www.baidu.com'
radio_fields,详细页面时,使用radio显示选项(FK默认使用select)
- radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL
show_full_result_count = True,列表时,模糊搜索后面显示的数据个数样式
- @admin.register(models.UserInfo)
- class UserAdmin(admin.ModelAdmin):
- # show_full_result_count = True # 1 result (12 total)
- # show_full_result_count = False # 1 result (Show all)
- search_fields = ('user',)
form = ModelForm,用于定制用户请求时候表单验证
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 = "指定列数据为空时,默认显示"
Django内置Admin解析的更多相关文章
- Django内置Admin
Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.contrib.contenttyp ...
- 框架----Django内置Admin
Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.contrib.contenttyp ...
- Django_内置Admin
Django内置Admin Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.co ...
- 76、django之内置Admin
本篇导航: 配置路由 定制Admin Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django ...
- django之内置Admin
本篇导航: 配置路由 定制Admin Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django ...
- Django内置模板标签
Django内置标签总览 可以查询下表来总览Django的内置标签: 标签 说明 autoescape 自动转义开关 block 块引用 comment 注释 csrf_token CSRF令牌 cy ...
- Django内置过滤器详解附代码附效果图--附全部内置过滤器帮助文档
前言 基本环境 Django版本:1.11.8 Python版本:3.6 OS: win10 x64 本文摘要 提供了常用的Django内置过滤器的详细介绍,包括过滤器的功能.语法.代码和效果示例. ...
- JSON和Django内置序列化
JSON 什么是JSON JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级的文本数据交换格式 JSON 独立于语言 * J ...
- AJAX—JSON和Django内置序列化
JSON 什么是JSON JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级的文本数据交换格式 JSON 独立于语言 * J ...
随机推荐
- ubuntu终端使用代理
sudo http_proxy=http://your_proxy:proxy_port dropbox start -i or sudo https_proxy=http://your_proxy: ...
- Linux服务器 大量的CLOSE_WAIT、TIME_WAIT解决办法
http://itindex.net/detail/50213-%E6%9C%8D%E5%8A%A1%E5%99%A8-time_wait-close_wait http://itindex.net/ ...
- 在odl中怎样实现rpc
opendaylight作为sdn主要开源项目,採用osgi框架.已经得到非常多厂商的支持.氦版本号也公布在即. 以下介绍一下在odl中怎样实现rpc. odl使用yang作为model模型定义文件. ...
- django用户认证系统——自定义认证后台8
Django auth 应用默认支持用户名(username)进行登录.但是在实践中,网站可能还需要邮箱.手机号.身份证号等进行登录,这就需要我们自己写一个认证后台,用于验证用户输入的用户信息是否正确 ...
- iOS开发之--制作属于自己的frameWork
开发的时候,有时候,我们会遇到协同开发,在协同开发的时候,每个开发者都会创建自己的工具类,还有就是当一个项目需要嵌套到另一个项目里面,这些时候,如果能把所需的部分打包成framework,会方便很多, ...
- java was started but returned exit code=1
将eclipse.ini文件删掉, 重启eclipse 会自动生成一个eclipse.ini就可以了~
- location.assign 与 location.replace的区别
window.location.assign(url) : 加载 URL 指定的新的 HTML 文档. 就相当于一个链接,跳转到指定的url,当前页面会转为新页面内容,可以点击后退返回上一个页面. w ...
- GetDesktopWindow和GetWindow区别
GetWindow The GetWindow function retrieves a handle to a window that has the specified relationship ...
- 下载flv格式视频
我们再看flash plaer播放视频时,有些时候需要下载,无奈找不到下载的按钮.这时,我们可以用以下的方式来进行下载. 其它格式估计也是有迹可循,大家仔细看看网页源代码,看到类似于这种地址,看到有相 ...
- poj 1182 食物链 (带关系的并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44835 Accepted: 13069 Description 动 ...