自定义 Django admin
核心观点
- UI是很重要的。
- 考虑初学者,DashBoard。
- 导航。
- 用户工作流。
- Django admin 缺少 WYSIWYG,文件管理,undo。
建议
- 了解用户的行业和工作流。
- 了解客户团队中的各个不同角色。
- 使用客户习语。
- 了解之前使用的工具,及其优缺点。
实现
ModelAdmin Media
class ArticleAdmin(admin.ModelAdmin):class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
优点:对于“一次性”项目简单。
缺点:只对Change Form有效。
Custom Templates
关键模板
admin/base.htmladmin/index.html
admin/change_form.html
admin/change_list.html
app_index.html
delete_confirmation.html
object_history.html
覆盖范围
Across an entire projectadmin/change_form.html
Across an application
admin/<my_app>/change_form.html
For an individual model
admin/<my_app>/<my_model>/change_form.html
例如:
{% extends "admin/change_list.html" %}{% block object-tools %}
<h1 class="errornote">
Look Here!
</h1>
{{ block.super }}
{% endblock %}
自定义模板的建议:
Extend, don't overrideUse {{ block.super }} to extend blocks
Extend a symlink of the admin templates in the event of recursion
Extend the extrahead block in base.html for admin-wide media
已有项目:
http://code.google.com/p/sorl-curator/http://code.google.com/p/django-grappelli/
ModelAdmin/ModelForm Hacking
注册ModelAdmin
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from demo_app.models import UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
fk_name = 'user'
max_num = 1
class CustomUserAdmin(UserAdmin):
inlines = [UserProfileInline, ]
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
行级别的权限
class ArticleAdmin(admin.ModelAdmin):def save_model(self, request, obj, form,
change):
obj.user = request.user
obj.save()
def queryset(self, request):
qs = self.model._default_manager.filter(user=request.user)
return qs
ModelForm
class AuthorForm(forms.ModelForm):exclude_states = ['AS', 'GU', 'MP', 'VI',]
def __init__(self, *args, **kwargs):
super(AuthorForm, self).__init__(*args,
**kwargs)
w = self.fields['state'].widget
choices = []
for key, value in w.choices:
if key not in self.exclude_states:
choices.append((key, value))
w.choices = choices
class AuthorAdmin(admin.ModelAdmin):
form = AuthorForm
Custom Views
Custom View URL
class PostAdmin(admin.ModelAdmin):def my_view(self, request):
return admin_my_view(request, self)
def get_urls(self):
urls = super(PostAdmin, self).get_urls()
my_urls = patterns('',
(r'^my_view/$', self.my_view)
)
return my_urls + urls
Custom View
@permission_required('blog.add_post')def admin_my_view(request, model_admin):
opts = model_admin.model._meta
admin_site = model_admin.admin_site
has_perm = request.user.has_perm(opts.app_label /
+ '.' + opts.get_change_permission())
context = {'admin_site': admin_site.name,
'title': "My Custom View",
'opts': opts,
'root_path': '/%s' % admin_site.root_path,
'app_label': opts.app_label,
'has_change_permission': has_perm}
template = 'admin/demo_app/admin_my_view.html'
return render_to_response(template, context,
context_instance=RequestContext(request))
Custom View Template
{% extends "admin/base_site.html" %}{% load i18n %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../../../">{% trans "Home" %}</a> ›
<a href="../../">{{ app_label|capfirst|
escape }}</a> ›
{% if has_change_permission %}<a
href="../">{{ opts.verbose_name_plural|
capfirst }}</a>{% else %}{{ opts.verbose_name_plural|
capfirst }}{% endif %} › My Custom View
</div>
{% endblock %}
{% block content %}
<!-- do stuff here -->
{% endblock %}
Django的内置模板
base.html
<head><title> {% block title %}{% endblock %} </title>
{% block extrastyle %}{% endblock %}
{% block extrahead %}{% endblock %}
</head>
{% load i18n %}
<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}">
<!-- Container -->
<div id="container">
<div id="header">
<div id="branding">
{% block branding %}{% endblock %}
</div>
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title }}{% endif %}</div>{% endblock %}
<!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% block pretitle %}{% endblock %}
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
{% block content %}
{% block object-tools %}{% endblock %}
{{ content }}
{% endblock %}
{% block sidebar %}{% endblock %}
<br class="clear" />
</div>
<!-- END Content -->
{% block footer %}<div id="footer"></div>{% endblock %}
</div>
<!-- END Container -->
</body>
base_site.html
{% extends "admin/base.html" %}{% load i18n %}
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
{% block branding %}
<h1 id="site-name">
{% trans 'Customized Admin' %}
</h1>
{% endblock %}
{% block dashboard %}
{% endblock %}
{% block nav-global %}{% endblock %}