咱们根据数据库创建了多个model,此时这个model也是用的admin的原生的模板,由于每一个model的样式可能会不同,此时咱们能够这样作。
假如咱们要修更名字为back的app的,且model名siteinfo的的change页面,则咱们能够按照以下步骤javascript
(1)在项目的templates创建admin/back/siteinfohtml
(2)在此目录下创建change_form.html便可java
项目目录:jquery
- shuili
- |-- back
- | |-- admin.py
- | |-- admin.pyc
- | |-- apps.py
- | |-- backcontroller.py
- | |-- backcontroller.pyc
- | |-- __init__.py
- | |-- __init__.pyc
- | |-- migrations
- | | |-- 0001_initial.py
- | | |-- 0001_initial.pyc
- | | |-- __init__.py
- | | `-- __init__.pyc
- | |-- models.py
- | |-- models.pyc
- | |-- tests.py
- | `-- views.py
- |-- manage.py
- |-- run.py
- |-- shuili
- | |-- __init__.py
- | |-- __init__.pyc
- | |-- settings.py
- | |-- settings.pyc
- | |-- urls.py
- | |-- urls.pyc
- | |-- wsgi.py
- | `-- wsgi.pyc
- `-- templates
- |-- admin
- | |-- back
- | | `-- siteinfo
- | | `-- change_form.html
- | `-- change_form.html
- `-- index.html
详细:
admin的禅宗
做为它的核心,Django的admin设计用来为以下的一个单独的活动:
受信任的用户编辑结构化的内容
是的,很简单,可是这简单的一行隐藏着不少内容,Django的admin的整个哲学都基于此
让咱们深刻了解这个句子的子内容:
"受信任的用户"
admin设计来被你(开发者)信任的人用,这不只仅表示那些被受权的用户,它表示Django假设你的内容编辑者能够
被信任来作正确的事情,这意味着编辑内容没有批准的过程,若是你信任你的用户,没有人须要对编辑的批准
这也代表了权限系统不支持基于一个对象的限制访问
若是你信任某人来编辑他本身的故事,你也将信任他不会在没有权限的状况下编辑别人的故事
"编辑"
Django的admin的首要目的是让人们编辑内容,这最初看起来很显而易见,可是也存在一些细小而强大的影响
例如,尽管admin对从新视查数据颇有用,可是它不是设计来干这个的,注意缺乏"can view"权限(参考第12章)
Django假设若是用户被容许在admin里查看内容,他们也被容许编辑它
另一个很值得注意的地方是admin缺乏一些例如"工做流"的东西,若是一些任务须要几步来完成,admin不支持
特别的顺序来作这件事情,admin关注于编辑,而不是围绕编辑的其它活动
对于工做流的缺少支持也起源于信任的原则,admin的哲学是,工做流属于我的问题,而不该该用代码实现
最后,注意admin缺少统计的支持,它不支持显示总数,平均数等等
再一次说明,admin是用来编辑的,它指望你写自定义的视图来完成其它的任务
"结构化的内容"
由于Django其它部分的关系,admin但愿你与结构化的数据工做,这样,admin仅仅支持编辑用Django模型存储的数据
对于其它形式的数据,你则须要自定义视图
总结
如今应该很清楚了,Django的admin不是给任何用户来作任何事情的,而是紧紧的关注一点而且把这一点作的很是好
当咱们须要扩展Django的admin时,同一哲学的大部份内容存在与此(注意扩展性无处不在)
由于自定义的Django视图能够作任何事情,并且它们能够可视化的集成到admin(参看下面内容),内建的定制admin的
机会在必定程序上被设计所限制
定制admin模板
咱们下面将看到,你有几种工具来定制内建的admin模板,可是对于其它任务,例如须要自定义工做流或者细粒度权限
你将须要阅读本章末尾讲到的定制admin视图
如今咱们来看看快速定制admin的外观和行为,第6章讲到了一些常见的任务,如更改logo样式和提供自定义admin表单
就这点来讲,咱们一般须要更改一个特殊项的一些模板
admin的每个视图,如更改列表,编辑表单,删除确认页面,历史视图等都有一个分配的模板
而这个模板能够经过几种方式来覆盖
首先,你能够全局覆盖模板,admin视图使用标准模板载入机制来寻找模板,因此若是你在你的模板目录里建立模板
Django将载入并使用这些模板而不是使用Django绑定的默认admin模板
这些全局模板以下:
视图 基本模板名
更改列表 admin/change_list.html
增长/编辑表单 admin/change_form.html
删除确认 admin/delete_confirmation.html
对象历史 admin/object_history.html
尽管如此,大多数状况下你只想更改一个单独的对象或者app的模板而不是全局的模板
这样的话,每一个admin视图首先寻找模型和app专有的模板,这些视图按下面的顺序寻找模板:
admin/<app_lable>/<object_name>/<template>.html
admin/<app_lable>/<template>.html
admin/<template>.html
例如,在bookstore app的Book模型的增长/编辑表单的视图(第6章的例子)按下面的顺序寻找模板:
admin/bookstore/book/change_form.html
admin/bookstore/change_form.html
admin/change_form.html
定制模型模板
大多数状况下,你想使用上面第一个模板来建立模型专有的模板
一般状况下经过扩展基本模板并在其中的块定义中添加信息会将这个任务完成的最好
例如咱们想在book页面顶端添加一些帮助内容,可能像下面这样:
[img][/img]
这很容易作到,建立一个叫admin/bookstore/book/change_form.html的模板而且插入下面的代码:
数据库
- {% extends "admin/change_form.html" %}
-
- {% block form_top %}
- <p>Insert meaningful help message here..</p>
- {% endblock %}
- {% extends "admin/change_form.html" %}
-
- {% block form_top %}
- <p>Insert meaningful help message here..</p>
- {% endblock %}
全部的这些模板都定义了一些块来让你覆盖,对于大多数程序,代码就是最好的文档,因此咱们鼓励你浏览admin模板
(在django/contrib/admin/templates/里面)来获得最新的信息
定制JavaScript
使用这个自定义的模型模板最多见的用途就是添加自定义的JavaScript到admin页面,多是实现一些特殊的小窗口部件
或者是客户端行为
幸运的是,这再简单不过了,每一个admin模板定义了一个{% block extrahead %},你能够把使用它来把其它的内容添加
到head元素里去,例如你想在你的一个admin历史页面引入jQuery:
- {% extends "admin/object_history.html" %}
-
- {% block extrahead %}
- <script src="http://media.example.com/javascript/jquery.js" type="text/javascript"></script>
- <script type="text/javascript">
-
-
-
- </script>
- {% endblock %}
- {% extends "admin/object_history.html" %}
-
- {% block extrahead %}
- <script src="http://media.example.com/javascript/jquery.js" type="text/javascript"></script>
- <script type="text/javascript">
-
-
-
- </script>
- {% 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视图的引入行以前
- (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'),
- (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'),
完整的URL配置可能像下面这样:
- from django.conf.urls.defaults import *
-
- urlpatterns = patterns('',
- (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'),
- (r'^admin/', include('django.contrib.admin.urls')),
- )
- from django.conf.urls.defaults import *
-
- urlpatterns = patterns('',
- (r'^admin/bookstore/report/$', 'bookstore.admin_views.report'),
- (r'^admin/', include('django.contrib.admin.urls')),
- )
为何把自定义视图放在admin引入以前?回想一下Django处理URL模式的顺序,由于admin的引入URL匹配几乎全部的东西
若是咱们把上面的两行URL配置代码调换顺序,Django将会查找一个内建的视图来匹配这个URL,这将不能工做
在这种特殊状况下,Django将试图载入bookstore app的Report模型的更改列表,这是不存在的
如今让咱们来写咱们的视图,为了简单起见,咱们只是载入全部的books在context里并让模板使用{% regroup %}标签处理
分组,用下面的代码建立一个bookstore/admin_views.py文件:
- from bookstore.models import Book
- from django.template import RequestContext
- from django.shortcuts import render_to_response
- from django.contrib.admin.views.decorators import staff_member_required
-
- @staff_member_required
- def report(request):
- return render_to_response(
- "admin/bookstore/report.html",
- {'book_list' : Book.objects.all()},
- RequestContext(request, {}),
- )
- from bookstore.models import Book
- from django.template import RequestContext
- from django.shortcuts import render_to_response
- from django.contrib.admin.views.decorators import staff_member_required
-
- @staff_member_required
- def report(request):
- return render_to_response(
- "admin/bookstore/report.html",
- {'book_list' : Book.objects.all()},
- RequestContext(request, {}),
- )
由于咱们把分组留给模板来作,这个视图很是简单,尽管如此,这里有一些细小的东西值得解释:
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的一部分:
- {% extends "admin/base_site.html" %}
-
- {% block title %}List of books by publisher{% endblock %}
-
- {% block content %}
- <div id="content-main">
- <h1>List of books by publisher:</h1>
- {% regroup book_list|dictsort:"publisher.name" by publisher as books_by_publisher %}
- {% for publisher in books_by_publisher %}
- <h3>{{ publisher.grouper }}</h3>
- <ul>
- {% for book in publisher.list|dictsort:"title" %}
- <li>{{ book }}</li>
- {% endfor %}
- </ul>
- {% endfor %}
- </div>
- {% endblock %}
- {% extends "admin/base_site.html" %}
-
- {% block title %}List of books by publisher{% endblock %}
-
- {% block content %}
- <div id="content-main">
- <h1>List of books by publisher:</h1>
- {% regroup book_list|dictsort:"publisher.name" by publisher as books_by_publisher %}
- {% for publisher in books_by_publisher %}
- <h3>{{ publisher.grouper }}</h3>
- <ul>
- {% for book in publisher.list|dictsort:"title" %}
- <li>{{ book }}</li>
- {% endfor %}
- </ul>
- {% endfor %}
- </div>
- {% 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配置:
- (r'^admin/bookstore/book/add/$', 'bookstore.admin_views.add_by_isbn'),
- (r'^admin/bookstore/book/add/$', 'bookstore.admin_views.add_by_isbn'),
若是这段代码在你的URL配置中放在admin的URL前面的话,add_by_isbn视图将彻底替代标准的admin视图
咱们能够遵循相似的动做来替代删除确认页面,编辑页面或者admin的任何其它部分