天天看點

Django 1.10中文文檔:第一個應用 part 7Polls Administration

已經同步到gitbook,想閱讀的請轉到gitbook: Django 1.10 中文文檔

Writing your first Django app, part 7¶

This tutorial begins where Tutorial 6 left off. We’re continuing the Web-poll application and will focus on customizing Django’s automatically-generated admin site that we first explored in Tutorial 2.

緊接着Tutorial 6。我們繼續開發投票應用并主要關注Django自動生成的admin站點,這部分我們在教程2中已經了解過。

Customize the admin form¶

By registering the Question model with admin.site.register(Question), Django was able to construct a default form representation. Often, you’ll want to customize how the admin form looks and works. You’ll do this by telling Django the options you want when you register the object.

通過admin.site.register(Question)語句将Question模型注冊到admin,Django會自動生成該模型的預設表單。一般情況下,你需要定制表單的樣式和功能。這樣在你注冊模型的時候就需要告訴Django你想要的選項。

Let’s see how this works by reordering the fields on the edit form. Replace the admin.site.register(Question)

line with:

我們通過示範對表單字段的重新排序,來了解其工作原理。用以下代碼替換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)
           

You’ll follow this pattern – create a model admin class, then pass it as the second argument to admin.site.register() – any time you need to change the admin options for a model.

一般遵循以下步驟——建立一個model admin類,然後作為admin.site.register()的第二個參數——你可以随時修改模型的admin選項。

This particular change above makes the “Publication date” come before the “Question” field:

這個操作将使“Publication date” 放在“Question” 字段之前:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

This isn’t impressive with only two fields, but for admin forms with dozens of fields, choosing an intuitive order is an important usability detail.

隻有兩個字段的情況下,感覺沒什麼作用,但是對于有幾十個字段的表單來說,采用更直覺的排序方式将是一個值得引起注意的細節問題。

And speaking of forms with dozens of fields, you might want to split the form up into fieldsets:

而且對于有幾十個字段的表單來說,你也許想要通過fieldsets來分隔開:

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)
           

The first element of each tuple in fieldsets is the title of the fieldset. Here’s what our form looks like now:

fieldsets 内元組的第一個字段是fieldsets的标題。我們的表單看起來應該像以下這樣了:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

Adding related objects¶

OK, we have our Question admin page, but a Question

has multiple Choices, and the admin page doesn’t display choices.

好的,我們已經有Question的admin頁面了,但是一個Question有很多個Choices,admin頁面也沒有展示這些choices。

Yet. There are two ways to solve this problem. The first is to register Choice with the admin just as we did with Question. That’s easy:

但是,我們有兩種方法來解決這個問題。第一種方法是像Question一樣将Choice注冊到admin站點,這非常簡單:

polls/admin.py

from django.contrib import admin

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

Now “Choices” is an available option in the Django admin. The “Add choice” form looks like this:

現在“Choices”已經展示在Django admin站點了,“增加choice”表單看起來如下圖:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

In that form, the “Question” field is a select box containing every question in the database. Django knows that a ForeignKey should be represented in the admin as a box. In our case, only one question exists at this point.

在這個表單中,“Question”字段是一個包含資料庫中所有Question的的單選框。Django知道這是ForeignKey ,應該在admin中作為單選框來展示。在我們的例子中,隻有一個Question存在。

Also note the “Add Another” link next to “Question.” Every object with a ForeignKey relationship to another gets this for free. When you click “Add Another”, you’ll get a popup window with the “Add question” form. If you add a question in that window and click “Save”, Django will save the question to the database and dynamically add it as the selected choice on the “Add choice” form you’re looking at.

同時注意到Question附近的“增加另一個”的連結按鈕。每個

ForeignKey 關系的對象都會自動有這個按鈕。當你點選“Add Another”,會彈出一個“Add Question”表單。如果你通過那彈窗點選save增加一個Question,Django會儲存這個Question到資料庫并在 “Add choice”表單中增加一個可選項。

But, really, this is an inefficient way of adding Choice

objects to the system. It’d be better if you could add a bunch of Choices directly when you create the Question

object. Let’s make that happen.

但是,這真的不是增加Choice高效途徑。當你建立一個Question的時候,如果你能增加一打choices該多好。讓我們試試看。

Remove the register() call for the Choice model. Then, edit the Question registration code to read:

去掉register()調用Choice模型的代碼,然後編輯Question 的注冊代碼,如下:

polls/admin.py

from django.contrib import admin

from .models import Choice, Question


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


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

admin.site.register(Question, QuestionAdmin)
           

This tells Django: “Choice objects are edited on the Question admin page. By default, provide enough fields for 3 choices.”

這告訴Django:“Choice對象可在Question的admin頁面編輯。預設情況下,有3個choices字段”

Load the “Add question” page to see how that looks:

通路“Add question” 頁,看看它長啥樣:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

It works like this: There are three slots for related Choices – as specified by extra – and each time you come back to the “Change” page for an already-created object, you get another three extra slots.

它的工作原理如下:有3個表單元件關聯Choice對象,而且當你每次回到一個已存在對象的change頁面時,你又會看到三個新的表單元件

At the end of the three current slots you will find an “Add another Choice” link. If you click on it, a new slot will be added. If you want to remove the added slot, you can click on the X to the top right of the added slot. Note that you can’t remove the original three slots. This image shows an added slot:

在三個表單元件的最後,你可以看到“Add another Choice”連結,點選它後,會建立一個新的表單選項。。如果你想移除已增加的槽,點選右上角X即可。注意你不能去掉那三個原有的槽。下圖展示增加一個槽:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

One small problem, though. It takes a lot of screen space to display all the fields for entering related Choice objects. For that reason, Django offers a tabular way of displaying inline related objects; you just need to change the ChoiceInline declaration to read:

然後,還有個小問題。展示所有關聯的Choice對象會占據非常多的螢幕空間。為此,Django提供了一個扁平化的顯示方式。你隻需要将ChoiceInline 類替換即可,如下:

polls/admin.py

class ChoiceInline(admin.TabularInline):
    #...
           
Django 1.10中文文檔:第一個應用 part 7Polls Administration

Note that there is an extra “Delete?” column that allows removing rows added using the “Add Another Choice” button and rows that have already been saved.

注意有一個 “Delete?”列,允許你删除通過“Add Another Choice” 按鈕增加并儲存的行。

Customize the admin change list¶

Now that the Question admin page is looking good, let’s make some tweaks to the “change list” page – the one that displays all the questions in the system.

現在Question的admin頁面已經非常漂亮了,我們繼續對“change list”做一下微調——就是那個展示所有Question清單的頁面

Here’s what it looks like at this point:

這就是它現在的樣子:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

By default, Django displays the str()

of each object. But sometimes it’d be more helpful if we could display individual fields. To do that, use the list_display admin option, which is a tuple of field names to display, as columns, on the change list page for the object:

預設情況下,Django調用str()展示每個對象。但是有時候,如果我們可以展示其他的字段的話,将會更好。為此,你可以用list_display 選項,這是想要展示的字段名的集合,在change list頁面上将作為列來展示:

polls/admin.py

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

Just for good measure, let’s also include the was_published_recently()

method from Tutorial 2:

更好的是,我們也可以展示was_published_recently()方法:

polls/admin.py

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date', 'was_published_recently')
           

Now the question change list page looks like this:

現在Question的change list頁面看起來如下圖:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

You can click on the column headers to sort by those values – except in the case of the was_published_recently header, because sorting by the output of an arbitrary method is not supported. Also note that the column header for was_published_recently is, by default, the name of the method (with underscores replaced with spaces), and that each line contains the string representation of the output.

你可以點選列标題來排序——除了was_published_recently外,因為arbitrary 方法的輸出并不支援排序。同時注意was_published_recently 列标題,預設下是函數名(下劃線替換為了空格),内容則是輸出的字元串表示法。

You can improve that by giving that method (in polls/models.py) a few attributes, as follows:

你可以在polls/models.py中增加如下屬性來修複這個問題:

polls/models.py

class Question(models.Model):
    # ...
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=) <= self.pub_date <= now
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'
           

For more information on these method properties, see list_display.

想了解跟多資訊,請看 list_display.

Edit your polls/admin.py file again and add an improvement to the Question change list page: filters using thelist_filter. Add the following line to QuestionAdmin:

再次編輯polls/admin.py,并進一步改善Question change list頁面:用list_filter來作過濾器。在QuestionAdmin類裡加如下行:

list_filter = ['pub_date']
           

That adds a “Filter” sidebar that lets people filter the change list by the pub_date field:

這會增加一個過濾器面闆,讓使用者可以通過pub_date 來過濾change list頁面:

Django 1.10中文文檔:第一個應用 part 7Polls Administration

The type of filter displayed depends on the type of field you’re filtering on. Because pub_date is a DateTimeField, Django knows to give appropriate filter options: “Any date”, “Today”, “Past 7 days”, “This month”, “This year”.

根據你選擇的過濾條件的不同,Django會在面闆中添加不容的過濾選項。由于pub_date是一個DateTimeField,是以,Django自動添加了這些選項:“Any date”, “Today”, “Past 7 days”, “This month”, “This year”。

This is shaping up well. Let’s add some search capability:

為了做的更好。我們再增加搜尋框:

search_fields = ['question_text']
           

That adds a search box at the top of the change list. When somebody enters search terms, Django will search the question_text field. You can use as many fields as you’d like – although because it uses a LIKE query behind the scenes, limiting the number of search fields to a reasonable number will make it easier for your database to do the search.

這會在頁面的頂部增加一個搜尋框。當輸入搜尋關鍵字後,Django會在question_text字段内進行搜尋。隻要你願意,你可以使用任意多個搜尋字段,Django在背景使用的都是SQL查詢語句的LIKE文法,但是,有限制的搜尋字段有助于背景的資料庫查詢效率。

Now’s also a good time to note that change lists give you free pagination. The default is to display 100 items per page. Change list pagination, search boxes, filters, date-hierarchies, and column-header-ordering all work together like you think they should.

現在你應該注意到 了,change list有分頁功能,預設下顯示100個每頁。現在,Change list pagination, search boxes, filters, date-hierarchies, and column-header-ordering等,都以你想的方式工作了。

Customize the admin look and feel¶

定制admin外觀¶

Clearly, having “Django administration” at the top of each admin page is ridiculous. It’s just placeholder text.

很明顯,在每一個admin頁面頂端都顯示“Django administration”是很可笑的,它僅僅是個占位文本。

That’s easy to change, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system.

利用Django的模闆系統,很容易修改它。Django的admin站點是由Django自己驅動的,用的也是Django自己的模闆接口。

Customizing your project’s templates¶

定制項目模闆¶

Create a templates directory in your project directory (the one that contains manage.py). Templates can live anywhere on your filesystem that Django can access. (Django runs as whatever user your server runs.) However, keeping your templates within the project is a good convention to follow.

在你的項目目錄(包含manage.py檔案的目錄)下建立templates目錄。Templates可以放在任何Django可以通路到的地方。(你的服務以什麼使用者跑,DJango就以什麼使用者運作)庵後,将你的templates目錄放在project下是非常好的習慣。

Open your settings file (mysite/settings.py

, remember) and add a DIRS option in the TEMPLATES setting:

打開settings配置檔案(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 is a list of filesystem directories to check when loading Django templates; it’s a search path.

DIRS是一個檔案系統目錄的清單,當加載Django模闆時,會在DIRS中進行查找。它是搜尋路徑。

Organizing templates

Just like the static files, we could have all our templates together, in one big templates directory, and it would work perfectly well. However, templates that belong to a particular application should be placed in that application’s template directory (e.g. polls/templates) rather than the project’s (templates). We’ll discuss in more detail in the reusable apps tutorial why we do this.

組織templates

就像靜态檔案一樣,我們可以把所有的模闆都放在一起,形成一個大大的模闆檔案夾,并且工作正常。但是我們不建議這樣!我們建議每一個模闆都應該存放在它所屬應用的模闆目錄内(例如polls/templates)而不是整個項目的模闆目錄(templates),因為這樣每個應用才可以被友善和正确的重用。請參考2.10節《如何重用apps》。

Now create a directory called admin inside templates, and copy the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into that directory.

接下來,在剛才建立的templates中建立一個admin目錄,将admin/base_site.html模闆檔案拷貝到該目錄内。這個html檔案來自Django源碼,它位于django/contrib/admin/templates目錄内。

Where are the Django source files?

If you have difficulty finding where the Django source files are located on your system, run the following command:

如果你不知道Django的源代碼檔案在哪,運作以下指令:

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

Then, just edit the file and replace{% raw %} {{ site_header|default:_('Django administration') }}{% endraw %} (including the curly braces) with your own site’s name as you see fit. You should end up with a section of code like:

編輯該檔案,用你喜歡的站點名字替換掉{% raw %} {{ site_header|default:_('Django administration') }}{% endraw %}(包括兩個大括号一起),看起來像下面這樣:

           

{% block branding %}

Polls Administration

{% endblock %}

“`

We use this approach to teach you how to override templates. In an actual project, you would probably use the django.contrib.admin.AdminSite.site_header attribute to more easily make this particular customization.

在這裡,我們使用這個方法教會你如何重寫模闆。但是在實際的項目中,你可以使用 django.contrib.admin.AdminSite.site_header,友善的對這個頁面title進行自定義。

This template file contains lots of text like {% block branding %} and {{ title }}. The {%

and {{ tags are part of Django’s template language. When Django renders admin/base_site.html, this template language will be evaluated to produce the final HTML page, just like we saw in Tutorial 3.

這個模闆檔案包含了大量的如{% raw %}{% block branding %} and {{ title }}{% endraw %},{% raw %} {% and {{ {% endraw %}是Django的模闆語言。當Django渲染 admin/base_site.html檔案時,這些模闆語言會生成最終的HTML頁面,就像Tutorial 3所說

Note that any of Django’s default admin templates can be overridden. To override a template, just do the same thing you did with base_site.html – copy it from the default directory into your custom directory, and make changes.

請注意,所有Django預設的admin模闆都可以被重寫。類似剛才重寫base_site.html模闆的方法一樣,從源代碼目錄将html檔案拷貝至你自定義的目錄内,然後修改檔案。

Customizing your application’s templates¶

定制 application’s 模闆¶

Astute readers will ask: But if DIRS was empty by default, how was Django finding the default admin templates? The answer is that, since APP_DIRS is set to True, Django automatically looks for a templates/ subdirectory within each application package, for use as a fallback (don’t forget that django.contrib.admin is an application).

聰明的讀者可能會問:但是DIRS預設是空的,Django是如何找到預設的admin模闆呢?回答是,由于APP_DIRS被設定為True,Django将自動查找每一個應用包内的templates/子目錄(不要忘了django.contrib.admin也是一個應用)。

Our poll application is not very complex and doesn’t need custom admin templates. But if it grew more sophisticated and required modification of Django’s standard admin templates for some of its functionality, it would be more sensible to modify the application’s templates, rather than those in the project. That way, you could include the polls application in any new project and be assured that it would find the custom templates it needed.

我們的投票應用不太複雜,是以不需要自定義admin模闆。但是如果它變得越來越複雜,因為某些功能而需要修改Django的标準admin模闆,那麼修改app的模闆就比修改項目的模闆更加明智。這樣的話,你可以将投票應用加入到任何新的項目中,并且保證能夠找到它所需要的自定義模闆。

See the template loading documentation for more information about how Django finds its templates.

檢視template loading documentation擷取更多關于Django如何查找模闆的資訊。

Customize the admin index page¶

定制admin 首頁¶

On a similar note, you might want to customize the look and feel of the Django admin index page.

很多人都會想定制化Django admin的首頁的外觀和感覺。

By default, it displays all the apps in INSTALLED_APPS that have been registered with the admin application, in alphabetical order. You may want to make significant changes to the layout. After all, the index is probably the most important page of the admin, and it should be easy to use.

預設情況下,首頁展示所有INSTALLED_APPS 中被注冊到admin的應用,你或許想改變一下布局。畢竟,首頁是admin站點最重要的頁面,它應該要簡單易用。

The template to customize is admin/index.html. (Do the same as with admin/base_site.html in the previous section – copy it from the default directory to your custom template directory). Edit the file, and you’ll see it uses a template variable called app_list. That variable contains every installed Django app. Instead of using that, you can hard-code links to object-specific admin pages in whatever way you think is best.

要定制的模闆是admin/index.html,(像上節中更改admin/base_site.html模闆一樣,從它預設的目錄拷貝到你的定制化模闆目錄)。編輯檔案,你會看到模闆有一個app_list的變量。你可以寫死連結到指定對象的admin頁面,使用任何你認為好的方法,用于替代這個app_list。

What’s next?¶

接下來學習什麼?¶

The beginner tutorial ends here. In the meantime, you might want to check out some pointers on where to go from here.

入門教程到這裡就結束了。此時,你應該轉到 where to go from here看看接下該學習什麼

If you are familiar with Python packaging and interested in learning how to turn polls into a “reusable app”, check out Advanced tutorial: How to write reusable apps.

或者你對Python包機制很熟悉,對如何将投票應用轉換成一個可重用的app感興趣,請看Advanced tutorial: How to write reusable apps.

繼續閱讀