.html例如,在bookstore app的Book模型的增加/编辑表单的视图(第6章的例⼦)按下⾯的顺序寻找模板:admin/bookstore/book/change_form.htmladmin/bookstore/change_form.htmladmin/change_form.html
定制模型模板
⼤多数情况下,你想使⽤上⾯第⼀个模板来创建模型专有的模板
通常情况下通过扩展基本模板并在其中的块定义中添加信息会将这个任务完成的最好例如我们想在book页⾯顶端添加⼀些帮助内容,可能像下⾯这样:[img][/img]
这很容易做到,创建⼀个叫admin/bookstore/book/change_form.html的模板并且插⼊下⾯的代码:Java代码
1. {% extends \"admin/change_form.html\" %} 2.
3. {% block form_top %}
4.
Insert meaningful help message here..
5. {% endblock %} [java]1. {% extends \"admin/change_form.html\" %} 2.
3. {% block form_top %}
4.
Insert meaningful help message here..
5. {% endblock %}所有的这些模板都定义了⼀些块来让你覆盖,对于⼤多数程序,代码就是最好的⽂档,所以我们⿎励你浏览admin模板
(在django/contrib/admin/templates/⾥⾯)来得到最新的信息定制JavaScript
使⽤这个⾃定义的模型模板最常见的⽤途就是添加⾃定义的JavaScript到admin页⾯,可能是实现⼀些特殊的⼩窗⼝部件或者是客户端⾏为
幸运的是,这再简单不过了,每个admin模板定义了⼀个{%block extrahead %},你可以把使⽤它来把其它的内容添加到head元素⾥去,例如你想在你的⼀个admin历史页⾯引⼊jQuery:
Java代码
1. {% extends \"admin/object_history.html\" %} 2.
3. {% block extrahead %}
4. 5. 10. {% endblock %} [java]
1. {% extends \"admin/object_history.html\" %} 2.
3. {% block extrahead %}
4. 5.
10. {% endblock %}
我不知道为什么你在对象历史页⾯需要jQuery,但是这个例⼦适⽤于admin的任何模板
你可以使⽤这个技术来引⼊任何其它你可能需要的JavaScript⼩窗⼝部件
定制admin视图
到⽬前为⽌那些想添加⾃定义⾏为到Django的admin中的⼈们可能开始困惑了,他们会喊,\"你所讲述的都是关于怎样改变admin的外观,但是我怎样改变admin的⼯作⽅式呢?\"好了,别喊了,这⾥就是答案
需要理解的第⼀件事就是它⼀点也不神奇,admin做的任何事都不特殊,它只是⼀些像其它视图⼀样处理数据的视图罢了这些视图在django.contrib.admin.views,当然这⾥有很多代码,它必须处理所有的选项,域类型和影响模型⾏为的设置同样的,当你意识到admin只是⼀些视图时,添加⾃定义的admin视图就变得更容易理解
让我们添加⼀个\"publisher report\"视图到我们第6章的book app中,我们将构建⼀个admin视图来显⽰通过publisher
分组的books列表,这是⼀个⾮常典型你可能想构建的⾃定义admin\"report\"的例⼦
⾸先我们在URLconf⾥⾯包装⼀个视图,我们需要把这⾏代码插⼊到admin视图的引⼊⾏之前
Java代码
1. (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'), [java]
1. (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'),
完整的URL配置可能像下⾯这样:
Java代码
1. from django.conf.urls.defaults import * 2.
3. urlpatterns = patterns('',
4. (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'), 5. (r'^admin/', include('django.contrib.admin.urls')), 6. ) [java]
1. from django.conf.urls.defaults import * 2.
3. urlpatterns = patterns('',
4. (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'), 5. (r'^admin/', include('django.contrib.admin.urls')), 6. )
为什么把⾃定义视图放在admin引⼊之前?回想⼀下Django处理URL模式的顺序,因为admin的引⼊URL匹配⼏乎所有的东西如果我们把上⾯的两⾏URL配置代码调换顺序,Django将会查找⼀个内建的视图来匹配这个URL,这将不能⼯作
在这种特殊情况下,Django将试图载⼊bookstore app的Report模型的更改列表,这是不存在的
现在让我们来写我们的视图,为了简单起见,我们只是载⼊所有的books在context⾥并让模板使⽤{% regroup %}标签处理
分组,⽤下⾯的代码创建⼀个bookstore/admin_views.py⽂件:
Java代码
1. from bookstore.models import Book
2. from django.template import RequestContext 3. from django.shortcuts import render_to_response
4. from django.contrib.admin.views.decorators import staff_member_required 5.
6. @staff_member_required 7. def report(request):
8. return render_to_response(
9. \"admin/bookstore/report.html\10. {'book_list' : Book.objects.all()}, 11. RequestContext(request, {}), 12. )
[java]
1. from bookstore.models import Book
2. from django.template import RequestContext 3. from django.shortcuts import render_to_response
4. from django.contrib.admin.views.decorators import staff_member_required 5.
6. @staff_member_required 7. def report(request):
8. return render_to_response(
9. \"admin/bookstore/report.html\10. {'book_list' : Book.objects.all()}, 11. RequestContext(request, {}), 12. )
因为我们把分组留给模板来做,这个视图⾮常简单,尽管如此,这⾥有⼀些细⼩的东西值得解释:
1,我们使⽤django.contrib.admin.views.decorators的staff_member_required装饰器,它类似于第12章讨论的
login_required装饰器,但是这个还检查给定的⽤户是否标记为\"staff\"成员来决定是否允许访问admin
这个装饰器保护所有内建的admin视图,让你的视图的认证逻辑和admin的其它部分匹配
2,我们渲染在admin/下⾯的模板,虽然这没有严格的要求,但是保持你所有的admin模板分组在⼀个admin⽬录下被认为是最佳实践,我们把模板放在我们的app后⾯叫bookstore的⽬录下也是最佳实践
3,我们使⽤RequestContext作为第3个参数(context_instance)传递给render_to_response
这保证了关于当前⽤户的信息可以在模板⾥得到,参看第10章得到更多关于RequestContext的信息
最后我们将为这个视图创建⼀个模板,我们继承内建的admin模板来使这个视图视觉上看起来是admin的⼀部分:
Java代码
1. {% extends \"admin/base_site.html\" %} 2.
3. {% block title %}List of books by publisher{% endblock %} 4.
5. {% block content %} 6.
7.
List of books by publisher:
8. {% regroup book_list|dictsort:\"publisher.name\" by publisher as books_by_publisher %} 9. {% for publisher in books_by_publisher %} 10.
{{ publisher.grouper }}
11.
16. {% endfor %} 17.
18. {% endblock %} [java]
1. {% extends \"admin/base_site.html\" %} 2.
3. {% block title %}List of books by publisher{% endblock %} 4.
5. {% block content %} 6.
7.
List of books by publisher:
8. {% regroup book_list|dictsort:\"publisher.name\" by publisher as books_by_publisher %} 9. {% for publisher in books_by_publisher %} 10.
{{ publisher.grouper }}
11.
16. {% endfor %} 17.
18. {% endblock %}
通过继承admin/base_site.html我们\"免费\"得到Django的admin的外观,它看起来像这样:[img][/img]
今天你需要在哪⾥使⽤admin?
你可以使⽤这个技术来向admin添加任何你想到的东西,记住所谓的\"定制admin视图\"事实上只是普通的Django视图
你可以使⽤你在本书其它部分所学的所有技术来构建任意复杂的admin视图
我们将以⼀些⾃定义admin视图的⼀些好注意结束本章内容覆盖内建的视图
默认的admin视图不包含这些,你可以很轻松的在admin的任何地⽅跳转到你的⾃定义视图,只需让你的URL覆盖掉内建的那些例如,我们可以⽤⼀个简单的让⽤户输⼊ISBN的表单替代内建的book创建视图,然后我们就可以从http://isbn.nu/来查询book信息和⾃动创建对象
这个视图的代码留给读者做练习,最重要的部分是下⾯的URL配置:
Java代码
1. (r'^admin/bookstore/book/add/$', 'bookstore.admin_views.add_by_isbn'), [java]
1. (r'^admin/bookstore/book/add/$', 'bookstore.admin_views.add_by_isbn'),
如果这段代码在你的URL配置中放在admin的URL前⾯的话,add_by_isbn视图将完全替代标准的admin视图
我们可以遵循类似的动作来替代删除确认页⾯,编辑页⾯或者admin的任何其它部分
贡献!
这个部分还没有完成,你有⼀些其它类型的⾃定义admin视图想覆盖吗?在这篇⽂章留下评注来让我们知道!