Django教程之八-----编写你的第一个Django应用(7)

这个教程紧跟教程(6)。我们将继续网页问卷调查应用并且将聚焦在定制Django的自动生成管理站点,这在教程(2)的时候我们有过首次接触。


1. 自定义管理形式

通过使用admin.site.register(Question)来注册Question模型,Django能组成一个默认的窗体展示。通常,你将想要自定义管理站点的外观和行为。当注册对象的时候你可以通过告诉Django你想要的选项来完成这个。


让我们看看通过在编辑窗体上重排序是如何工作的。用下面的代码替换这一行admin.site.register(Question):

polls/admin.py
from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question_text']

admin.site.register(Question, QuestionAdmin)

你遵照这种形式 -- 创建一个模型管理类,然后将它作为第二个参数传递给admin.site.register() -- 任何时候你需要改变一个模型的管理选项。


上面的特别的修改让“发布时间”出现在“Question”字段之前:


只有2个字段并不会让人印象深刻,但是对于有几十个字段的管理窗口来说,选择一个直观的顺序是一个重要的可用细节。


说到几十个字段的窗体,你也许想要将窗体拆分成字段集:

polls/admin.py
from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Question, QuestionAdmin)

在fieldsets中的每个元组的第一个元素是fieldset的标题。这就是我们窗体现在的样子:



2. 添加相关对象

OK,我们有了自己的管理页面,但是一个Question有多个Choices,但是管理站点没有显示choices。


仍然。


有2种方式来解决这个问题。第一个是像我们注册Question一样在admin中注册Choice。那很简单:

polls/admin.py
from django.contrib import admin

from .models import Choice, Question
# ...
admin.site.register(Choice)

现在“Choices”在Django管理里是一个可选项了。添加“choice”的窗体是这样的:


在那个窗体中,“Question”字段是一个选择框,它包含了数据库中的每个问题。Django知道ForeignKey在管理中应该作为一个<select>框来展示。在我们的情况下,目前只有一个问题存在。


同样要注意“Add Another”链接紧挨着"Question".每个和另外一个有ForeignKey关系的对象都能免费得到这个。当你点击"Add Another",你将会得到一个带有“Add Question”窗体的弹出窗口。如果你在哪个窗口添加了一个问题并且点击了"save",Django将会保存这个问题到数据库并且动态的添加它到你正在看的"Add choice“窗体的可选choice。


但是,事实上,这是添加choice到系统的低效方式。好点的方式是当你在创建Question对象的时候,你可以直接添加大量的Choices。让我们来实现这个。

移除Choice模型的register()调用。然后,像这样编辑Question注册:

polls/admin.py
from django.contrib import admin

from .models import Choice, Question


class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)

这告诉Django:”choice对象在Question管理页面被编辑。默认情况下提供最多3个choices。“


加载”Add question“页面看看效果:


它像这样工作:对相关的Choices有3个插槽 -- 正如extra指定的一样 -- 并且每次你回到一个已经创建对象的”修改“页面,你将会得到另外3个额外的插槽。


在当前3个插槽的底部你将会发现一个”Add another choice“链接。如果你点击它,一个新的插槽将会被添加。如果你想要移除这个新添加的插槽,你可以点击添加插槽右上角的X。注意,你不能移除原始的3个插槽。下面的图片展示了一个添加的插槽:


一个小问题,尽管。它占用了太多的屏幕空间在输入相关choice对象的时候来显示所有字段。因为那个原因,Django提供了一个表格的方式来显示内联相关对象;你只需要修改ChoiceInline描述:

polls/admin.py
class ChoiceInline(admin.TabularInline):
    #...

使用TabularInline(而不是StackedInline),相关的对象显示在一个更紧凑的表格式的格式:


注意这里有一个额外的”Delete?“列,它允许使用”Add Anoter Choice“按钮来移除已添加的行和已经保存过的行。


3. 自定义管理修改列表

现在Question管理页面看起来不错了,让我们调整”修改列表“页面 -- 在系统中显示所有问题的那个。


这是它现在看起来的样子:


默认的,Django显示每个对象的str()方法。但是一些时候如果我们能显示自己的字段将会很有帮助。为了做到那个,使用list_display管理选项,它是一个包含要显示的字段名称的元组,作为列,在对象的修改列表页面:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date')

为了更好的测评,让我们包括在教程(2)中的was_published_recently()方法:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date', 'was_published_recently')
现在问题修改列表看起来是这样:


你可以点击列头来排序这些值 -- 除了was_published_recently头,因为一个任意方法的输出的排序是不被支持的。同样注意was_published_recently的头,默认的,方法的名称(用空格代替下划线),并且每一行都包含输出的字符串展现。

你可以通过给那个方法(在polls/models.py)一些属性来改进这个,如下:
polls/models.py
class Question(models.Model):
    # ...
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'
想要了解这些方法属性的更多信息,请阅读<列表_显示>

再次编辑你的polls/admin.py文件并且添加一个对Question修改列表页面的改进处理:过滤器使用list_filter。将下列行添加到QuestionAdmin:
list_filter = ['pub_date']
那添加一个”filter“的侧边栏让用户可以使用pub_date字段来过滤修改列表:

过滤显示的类型取决于你过滤的字段的类型。因为pub_date是一个DateTimeField,Django知道提供一个适当的过滤选项:'Any date','Today','Past 7 days','this month','this year'.

这将要成型了,让我们添加一些搜索功能:
search_fields = ['question_text']
那在修改列表的顶部添加了一个搜索框。当某人输入搜索词时,Django将会搜索question_text字段。你可以使用你想要使用数量的字段 -- 尽管因为它在幕后使用了一个LIKE查询,将搜索字段的数量限制在一个合理的数量将会是数据搜索更为容易。

现在是注意的好时机,修改列表提供了免费的分页。默认是每页显示100个项。Change list pagination,search boxes,filters,date-hierarchies,和column-header-ordering都像你认为的那样工作在一起。

4. 自定义管理的外貌和感觉

明确的,在每个管理页面的顶部的”Django administration“是可笑的。它只是一个占位文本。


那很容易修改,尽管,使用Django的模板系统。Django管理是由Django本身驱动的,并且它的接口使用Django自己的模板系统。

4.1 自定义你项目的模板

在你的项目路径(包含manage.py的那个)下创建一个templates路径。模板能在你的文件系统的任何Django可以访问的地方。(Django作为你服务运行的任何用户来运行)然而,在项目中保持你的模板是一个良好的习惯。


打开你的设置文件(mysite/settings.py,记得)并在TEMPLATES设置中添加一个DIRS选项:

mysite/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

DIRS是一个文件系统路径的列表,用于检查什么时候加载Django模板;它是一个搜索路径。

组织模板

就像静态文件,我们可以将我们所有的模板一起放在一个大的模板目录下,并且它会运行的相当好。然而,属于一个特殊应用的模板应该被放在应用的模板路径(例如,polls/templates)而不是项目的(templates)我们将会在<复用应用教程>中讨论这些细节。

现在在templates里面创建一个admin的路径,然后将模板admin/base_site.html从Django源码的默认Django管理模板路径(django/contrib/admin/templates)拷贝到那个路径。

Django源码文件在哪里?

如果你找不到在你系统中的源码文件,运行下面的命令:

$ python -c "import django; print(django.__path__)"

然后,编辑那个文件,并且用你的站点名称来替换{{ site_header|default:_('Django administration') }}(包括花括号),你应该以这样一个代码来结束:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

我们使用这个方法来告诉你如何覆写模板。在一个真实的项目中,你可能用Django.contrib.admin.AdminSite.site_header属性来更容易的完成这个特殊的自定义。


模板文件包含很多的文本像{% block branding %}和{{ title }}。{% 和{{标签是Django模板语言的一部分。当Django渲染admin/base_site.html,这个模板语言将会评估来产生最终的HTML页面,就像我们在教程(3)中看到的一样。


注意任何Django默认的管理模板都可以被覆写。为了覆写一个模板,只要做你在base_site.html中做的一样 -- 从默认路径将它拷贝到你自定义路径然后修改。

4.2 自定义你应用的模板

聪明的读者也许会问:如果DIRS默认是空的,Django如何找到默认的管理模板?答案是,因为APP_DIRS被设置为True,Django自动在每个应用包里寻找templates/子路径,作为备用(不要忘记了django.contrib.admin是一个应用)。


我们的问卷调查应用不是非常复杂,并且不需要自定义管理模板。但如果它增长的复杂并且需要为了它的功能性对Django的白标准管理模板做一些修改,修改应用的模板将会是非常明智的,而不是项目的。那样,你可以将polls应用包含在任何新的项目并且确保它将会找到它需要的自定义模板。


关于Django如何找到它的模板的更多信息,请阅读<模板加载文档>


5. 自定义管理首页

同样,你也许想要自定义Django管理首页的样式和感觉。


默认的,它显示所有在管理应用中的INSTALLED_APPS中注册的所有应用,以字母排序的方式。你也许想要对布局做重大的改变。毕竟,首页可能是管理的最重要的页面,并且它应该容易使用。


自定义的模板是admin/index.html。(如先前在admin/base_site.html中做的一样 -- 从默认路径中拷贝它到你自定义的模板路径)。编辑文件,你将会看到它使用一个模板变量app_list。这个变量包含每一个安装了的Django应用。作为使用它的代替,你可以硬编码链接到指定对象的管理页面以你认为最好的方式。





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值