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 = Noneview_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 ...
随机推荐
- jqgrid的search
2015-04-19 本人近期的博客都是和之前的随笔相关联的. 今天想和大家分享的是jqgrid中的search. 相信大家写代码用到jqgrid的时候都可能会在jqgrid中涉及查询,其实查询和 增 ...
- Access 是/否 字段
Microsoft Access 数据库引擎 SQL 数据类型包含由 Microsoft® Jet 数据库引擎定义的 13 种主要数据类型,以及若干可识别为这些数据类型的有效同义词. 其中,在工作中遇 ...
- 一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制
开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法 ...
- cocos2d安卓自动编译脚本去掉复制Resources资源和签名功能
去掉这两个功能的原因: 1.因为有时候打包是分渠道的,不同的渠道资源也可能不一样,所以不能直接复制资源. 2.如果用cocostudio打release包,因为要输入签名地址,会导致在自动签名处停住不 ...
- Activity公用跳转到主Activity
public class VSession { private VSession() { } public static VSession getInstance() { if (session == ...
- 【BZOJ4379】[POI2015]Modernizacja autostrady 树形DP
[BZOJ4379][POI2015]Modernizacja autostrady Description 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径为最远的两个点的距离,请输 ...
- sass学习之一:sass安装compass部署
主要参考 http://www.jianshu.com/p/5bfc9411f58f -------------------------------------------- sass基于ruby 需 ...
- JavaWeb中servlet读取配置文件的方式
我们在JavaWeb中常常要涉及到一些文件的操作,比如读取配置文件,下载图片等等操作.那我们能不能采用我们以前在Java工程中读取文件的方式呢?废话不多说我们来看看下我们以前在Java工程中读取文件是 ...
- java反射——字段
大家都知道反射技术在Java里面时非常重要的一个技术点,因为Java好多框架的编写都是基于反射的,别的不多说,spring框架里面的IOC就是基于反射实现.那么什么是反射呢?JAVA反射机制是在运行状 ...
- Storm-源码分析-acker (backtype.storm.daemon.acker)
backtype.storm.daemon.acker 设计的巧妙在于, 不用分别记录和track, stream过程中所有的tuple, 而只需要track root tuple, 而所有中间过程都 ...