django實例:建立你的第一個應用投票系統(3)(4)



https://docs.djangoproject.com/en/1.5/intro/tutorial01/Django的管理面板默認是不開啓的,因此咱們須要進行一些設置工做
一、在INSTALLED_APPS裏面把 django.contrib.admin 前面的註釋去掉
二、運行css

python manage.py syncdb

,創建和管理有關的表
三、編輯mysite/urls.py文件,設置管理面板的url路由規則html

複製代碼

from django.conf.urls import patterns, include, url# Uncomment the next two lines to enable the admin:from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',    # Examples:
    # url(r'^如今啓動服務<div class="blockcode"><blockquote>python manage.py runserver

複製代碼

 

訪問http://127.0.0.1:8000/admin/ 會看到管理登陸頁面


輸入用戶名和密碼,就在上一節建立的超級用戶


固然如今仍是看不到咱們添加的投票管理項
在polls目錄下面添加admin.py頁面,內容以下python

from django.contrib import adminfrom polls.models import Poll
admin.site.register(Poll)

 

django會自動從新加載修改了的文件,但若是是新添加的文件,django是不會加載的,因此須要咱們重啓服務
如今再看看界面


這個是投票列表頁面,基本的what's up 是咱們添加的項


點擊 what's up編輯看看



自定義投票管理表單頁面
如今咱們看到的投票編輯頁面是根據咱們定義的模型自動生成的。如今咱們看看django是如何生成poll管理頁面的。

在剛纔添加的admin.py頁面裏面,用以下內容替換剛纔輸入的django

class PollAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question']
admin.site.register(Poll, PollAdmin)

看看頁面有什麼變化


再來看一個瀏覽器

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date']}),
    ]
admin.site.register(Poll, PollAdmin)

 

這種是給分組了,第一個字段爲每一個 fieldsets 的標頭


django還提供給每個 fieldset設置css類,函數

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]

 



如今已經在管理面板中看到poll了,但是它的選項在哪裏?

第一種方法和顯示Poll同樣測試

from polls.models import Choice
admin.site.register(Choice)

 

刷新看看,到添加頁面看看


django默認會把有外鍵的字段用 select下拉框來顯示


如今不論是添加投票項仍是選項都是在單獨的頁面吧,若是要想在投票頁面中直接就能夠添加選項要怎麼辦?url

複製代碼

from django.contrib import adminfrom polls.models import Choice, Pollclass ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
admin.site.register(Poll, PollAdmin)

複製代碼

 

意思是直接把Choice嵌入到poll管理頁面來編輯,默認添加3個choice,再打開poll 添加頁面看看



如今每次編輯返回查看的時候都會在下面多出3個空的選項,在最下面的一個選項下面有「Add another Choice」,點擊後會在下面自動添加一個選項


修改一下 ChoiceInline看看spa

class ChoiceInline(admin.TabularInline):    #...

 

StackedInline修改成TabularInline


顯示樣式從排列樣式變成了表格樣式。

自定義Poll管理列表顯示樣式

默認狀況下,會列出第個對象的str(),若是要想顯示更多的列就得須要list_display來實現調試

class PollAdmin(admin.ModelAdmin):    # ...
    list_display = ('question', 'pub_date')

 

咱們也把上次自定義添加的函數也加上

class PollAdmin(admin.ModelAdmin):    # ...
    list_display = ('question', 'pub_date', 'was_published_recently')

 



點擊表頭能夠排序,但是was_published_recently這個列卻不會。由於這個如今函數不支持。另外這個列的名字默認就是函數的名稱,顯示的內容就是函數輸出的結果。


再從新編輯一下polls/models.py

複製代碼

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

複製代碼

 

再次編輯polls/admin.py,在poll管理列表中添加一個過濾面板 在PollAdmin中添加以下代碼

list_filter = ['pub_date']

 



django會根據過濾條件列的類型自動生成一些選項。

還能夠添加上搜索框

search_fields = ['question']


還能夠加上時期類型的選擇

date_hierarchy = 'pub_date'

 

會在數據列表上面加一個分層的日期選項。具體效果能夠運行看看

接着再說一點有關模板的東西吧,若是想把左上角的logo換成咱們本身的要怎麼作呢。
一、在你的項目中新建 templates 目錄
二、把django默認的後面管理模板,按一些的目錄放到咱們新建的templates目錄下面,具體以下設置
在django的的源碼中django/contrib/admin/templates 把admin/base_site.html文件按一樣的目錄複製到新建的templates中即在templates中創建admin子目錄,而後把base_site.html複製到裏面,修改裏面的

Django site admin

 

字符串爲你要的
三、修改配置文件

TEMPLATE_DIRS = ('/path/to/mysite/templates', # 這裏寫你的目錄,只能是絕對路徑)



如今已經能夠在後臺管理投票了,如今就差怎麼在前臺顯示和如何投票了
一、index:首先第一個要有首頁,用來顯示全部的投票
二、detail:詳細信息頁面,用來顯示一個投票及相應的選項
三、results:結果頁面,用來查看一個投票的結果
以及一個投票的操做

在polls/views.py 頁面添加以下代碼

from django.http import HttpResponsedef index(request):    return HttpResponse("Hello, world. You're at the poll index.")

 

打開polls/urls.py,設置以下url路由信息

from django.conf.urls import patterns, urlfrom polls import views
urlpatterns = patterns('',
    url(r'^$', views.index, name='index')
)

 

打開項目下面的urls.py 即mysite/urls.py 用把poll應用下的url包含到主urls配置裏面。

複製代碼

from django.conf.urls import patterns, include, urlfrom django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
    url(r'^polls/', include('polls.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

複製代碼

 

打開http://localhost:8000/polls/ 測試一下看看。

若是要想往views裏面的方法傳遞參數要怎麼作呢
看看下面的
修改poll/url.py

複製代碼

from django.conf.urls import patterns, urlfrom polls import views
urlpatterns = patterns('',    # ex: /polls/
    url(r'^$', views.index, name='index'),    # ex: /polls/5/
    url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),    # ex: /polls/5/results/
    url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'),    # ex: /polls/5/vote/
    url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),
)

複製代碼

 

在polls/views.py添加

def detail(request, poll_id):    return HttpResponse("You're looking at poll %s." % poll_id)def results(request, poll_id):    return HttpResponse("You're looking at the results of poll %s." % poll_id)def vote(request, poll_id):    return HttpResponse("You're voting on poll %s." % poll_id)

 

若是在瀏覽器輸入http://localhost:8000/polls/34/,django是怎麼處理的呢
一、在mysite/url.py中先找到匹配的 '^polls/'
二、把匹配的url去掉,把剩餘 」34/" 傳遞給poll下面的url.py
三、在poll/url.py中找到匹配的項 r'^(?P<poll_id>\d+)/$' 執行相應的view : detail()
在執行detail()的時候至關於

detail(request=<HttpRequest object>, poll_id='34')

 

那麼這個34是如何對應到poll_id呢
在上面的第三步中,r'^(?P<poll_id>\d+)/$' 會把匹配出來的內容 34 和大家的正則組對應起來,poll_id對應匹配到的34


在上面寫的index view僅僅是測試的,沒有作具體的功能。

複製代碼

from django.http import HttpResponsefrom polls.models import Polldef index(request):
    latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
    output = ', '.join([p.question for p in latest_poll_list])    return HttpResponse(output)

複製代碼

 

上面的意思是取最新的5個記錄,以字符串的形式返回,並用「,」分開

模板

上面看到返回的內容的格式是直接寫到index裏面的,人們經常使用的要數據的邏輯處理和呈現分開就是這裏的狀況
這就用到django的模板功能了
創建文件:polls/templates/polls/index.html
內容以下

複製代碼

{% if latest_poll_list %}    <ul>
    {% for poll in latest_poll_list %}        <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}    </ul>{% else %}    <p>No polls are available.</p>{% endif %}

複製代碼

 

如今再修改index函數

複製代碼

from django.http import HttpResponsefrom django.template import Context, loaderfrom polls.models import Polldef index(request):
    latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = Context({        'latest_poll_list': latest_poll_list,
    })    return HttpResponse(template.render(context))

複製代碼

 

大概意思就是 先加載一個模板,設置一個字典數據,再用render方法把模板中和字典對應的變量用字典中的值處理

由於django模板功能常用,因此提供了一種簡化的代碼寫法。

複製代碼

from django.shortcuts import renderfrom polls.models import Polldef index(request):
    latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
    context = {'latest_poll_list': latest_poll_list}    return render(request, 'polls/index.html', context)

複製代碼

 

和上面是同樣的意思

404錯誤
這個錯誤咱們很常見,當對應的頁面不存在的時候就會出來

複製代碼

from django.http import Http404# ...def detail(request, poll_id):    try:
        poll = Poll.objects.get(pk=poll_id)    except Poll.DoesNotExist:        raise Http404    return render(request, 'polls/detail.html', {'poll': poll})

複製代碼

 

這裏尚未說到polls/detail.html模板,因此先在創建這個文件,簡單的寫入以下代碼,先不讓他出錯

{{ poll }}

 

若是在poll中對應的poll_id不存在的話就引起404錯誤。

像這種狀況會常常發生,因此django也提供了簡單的寫法

  1. from django.shortcuts import render, get_object_or_404

  2. # ...

  3. def detail(request, poll_id):

  4.     poll = get_object_or_404(Poll, pk=poll_id)

  5.     return render(request, 'polls/detail.html', {'poll': poll})

複製代碼

若是是要處理多個對象須要用這個:

get_list_or_404()

 

get_object_or_404

 

是同樣的功能,只是處理對象不一樣

若是發現錯誤了會在你的項目的url配置文件中找 handler404 對應的view來顯示,若是找不到的話會用django本身的viewdjango.views.defaults.page_not_found()來顯示,對於404文件也能夠用模板來設置
在項目模板中 mysite/templates 中添加404.html django會自動找到這個模板,而且顯示出來。

固然只有在DEBUG爲false的狀況下才會顯示出現,不然會顯示出一個具體的調試錯誤信息,可在settings.py文件裏面設置


如今繼續模板,修改polls/detail.html以下

複製代碼

<h1>{{ poll.question }}</h1>
<ul>{% for choice in poll.choice_set.all %}    <li>{{ choice.choice_text }}</li>{% endfor %}</ul>

複製代碼

 

{{ poll.question }} :django先以字典的形式在poll對象中查找question ,若是找不能以屬性的方式來查找,由於在這個例子裏question 就是poll的屬性,因此在這裏就找到了,若是還找不到的話就以列表索引的方式來查找。

poll.choice_set.all:這裏其實執行的是poll.choice_set.all()方法,會返回 Choice 的迭代對象

  1. 模板中的url引用

複製代碼

在上面代碼中

<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>

 

裏面的url鏈接是直接寫在模板裏面的,若是poll應用所在的位置改變了,就得須要在全部用到的模板裏面都修改修改。因此django有一種簡單的方法來實現。
還記得在poll/urls.py裏設置的url吧。
沒錯,注意在設置url的時候最後面有個 name 屬性,這個屬性就是來給每一個url一個名字,能夠在模板裏面直接用這個名字來代替url

<li><a href="{% url 'detail' poll.id %}">{{ poll.question }}</a></li>

 

注意:
若是設置{% url 'detail' poll.id %}不正常,而{% url detail poll.id %} 正常的話,說明你用的django版本<1.5,須要在模板的最上面添加:

{% load url from future %}

 

在poll.urls.py裏面是以下的定義

  1. # the 'name' value as called by the {% url %} template tag

  2. url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),

複製代碼

若是之後想要在其餘地方應用,或者不一樣的目錄結果中,只須要更改此處就能夠了,不用在每一個模板裏面更改,是否是很簡單

# added the word 'specifics'url(r'^specifics/(?P<poll_id>\d+)/$', views.detail, name='detail'),

 

url命名空間
假如如今有兩個應用,每一個應用下面的urls.py裏面都有一個detail 定義的url,這個時候django就無法判斷要用哪一個了,因此就出來了個命名空間。用來區別不一樣的url

複製代碼

from django.conf.urls import patterns, include, urlfrom django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
    url(r'^polls/', include('polls.urls', namespace="polls")),
    url(r'^admin/', include(admin.site.urls)),
)

複製代碼

 

再修改下模板文件

<li><a href="{% url 'detail' poll.id %}">{{ poll.question }}</a></li>

 

添加命名空間

<li><a href="{% url 'polls:detail' poll.id %}">{{ poll.question }}</a></li>
相關文章
相關標籤/搜索