Django Blog實戰

項目設置

? ? ? ?DEBUG 一個布爾型用來開啟或關閉項目的debug模式。如果設置為True,當你的應用拋出一個未被捕獲的異常時Django將會顯示一個詳細的錯誤頁面。當你準備部署項目到生產環境,請記住一定要關閉debug模式。永遠不要在生產環境中部署一個打開debug模式的站點因為那會暴露你的項目中的敏感數據。

? ? ?ALLOWED_HOSTS 當debug模式開啟或者運行測試的時候不會起作用(譯者注:最新的Django版本中,不管有沒有開啟debug模式該設置都會啟作用)。一旦你準備部署你的項目到生產環境并且關閉了debug模式,為了允許訪問你的Django項目你就必須添加你的域或host在這個設置中。


slug:

????????這個字段將會在URLs中使用。slug就是一個短標簽,該標簽只包含字母,數字,下劃線或連接線。我們將通過使用slug字段給我們的blog帖子構建漂亮的,友好的URLs。

ForeignKey:

? ? 我們通過related_name屬性指定了從UserPost的反向關系名。


定制models的展示形式

classPostAdmin(admin.ModelAdmin):

? ? ?list_display = ('title','slug','author','publish','status') ? ? #展示的字段

? ? ?list_filter = ('status','created','publish','author') ? ? #過濾返回結果

? ? ?search_fields = ('title','body') ? ? #搜索字段列

? ? ? prepopulated_fields = {'slug': ('title',)} ? ? #通過輸入的標題來填充slug字段

? ? ? raw_id_fields = ('author',)?

? ? ? date_hierarchy ='publish' ? ?#通過時間層快速導航的欄

? ? ? ordering = ['status','publish']


查詢集(QuerySet)和管理器(managers)

查詢集(QuerySet)是從你的數據庫中根據一些過濾條件范圍取回的結果對象進行的采集

每一個Django模型(model)至少有一個管理器(manager),默認管理器(manager)叫做objects。你通過使用你的模型(models)的管理器(manager)就能獲得一個查詢集(QuerySet)對象。獲取一張表中的所有對象,你只需要在默認的objects管理器(manager)上使用all()方法即可

Django的查詢集(QuerySets)是惰性(lazy)的,它們只會被動的去執行。這樣的行為可以保證查詢集(QuerySet)非常有效率。

我們之前提到過,objects是每一個模型(models)的默認管理器(manager),它會返回數據庫中所有的對象。但是我們也可以為我們的模型(models)定義一些定制的管理器(manager)。

有兩種方式可以為你的模型(models)添加管理器(managers):你可以添加額外的管理器(manager)方法或者繼承管理器(manager)的查詢集(QuerySets)進行修改。第一種方法類似Post.objects.my_manager(),第二種方法類似Post.my_manager.all()。我們的管理器(manager)將會允許我們返回所有帖子通過使用Post.published。

例:

class PublishedManager(models.Manager):

? ? def get_queryset(self):

? ? ? ? ?return super(PublishedManager, self).get_queryset().filter(status='published')

get_queryset()是返回執行過的查詢集(QuerySet)的方法


模型(models)的標準URLs

? ? ? ? ?Django的慣例是給模型(model)添加get_absolute_url()方法用來返回一個對象的標準URL。在這個方法中,我們使用reverse()方法允許你通過它們的名字和可選的參數來構建URLS。


模版

????????Django有一個強大的模板(templates)語言允許你指定數據的如何進行展示。它基于模板標簽(templates tags),{% load staticfiles %}告訴Django去加載django.contrib.staticfiles應用提供的staticfiles模板標簽(temaplate tags)。通過加載它,你可以在這個模板(template)中使用{% static %}模板過濾器(template filter)。通過使用這個模板過濾器(template filter),你可以包含一些靜態文件比如說blog.css文件

truncatewords用來縮短內容限制在一定的字數內

linebreaks用來轉換內容中的換行符為HTML的換行符


分頁

Django有一個內置的Paginator類允許你方便的管理分頁

例:

from django.core.paginator importPaginator, EmptyPage, PageNotAnInteger

def post_list(request):

? ? object_list = Post.published.all()?

? ? paginator = Paginator(object_list,3)# 3 posts in each page

? ? page = request.GET.get('page')

? ? try:?

? ? ? ? ? ?posts = paginator.page(page)

? ? except PageNotAnInteger:# If page is not an integer deliver the first page

? ? ? ? ? posts = paginator.page(1)

? ? except EmptyPage:# If page is out of range deliver last page of results

? ? ? ? ? posts = paginator.page(paginator.num_pages)

? ?return render(request,'blog/post/list.html', {'page': page,'posts': posts})


? ? ? ?現在,我們必須創建一個模板(template)來展示分頁處理,它可以被任意的模板(template)包含來使用分頁。在blog應用的templates文件夾下創建一個新文件命名為pagination.html。在該文件中添加如下HTML代碼:

<div class="pagination">

? ? ? ? <span class="step-links">

????????????????{% if page.has_previous %}

? ? ? ? ? ? ? ? ? ? ? ? <a href="?page={{ page.previous_page_number }}">上一頁</a>

? ? ? ? ????????{% endif %}

? ? ? ? ? ? ? ? <span class="current">Page {{ page.number }} of {{ ????????????????????????????page.paginator_num_pages }}

????????????????</span>

????????????????{% if page.has_next %}

????????????????????????<a href="?page={{ page.next_page_number }}">下一頁</a>

????????????????{% endif %}

????????</span>

</div>


為了渲染上一頁與下一頁的鏈接并且展示當前頁面和所有頁面的結果,這個分頁模板(template)期望一個Page對象。讓我們回到blog/post/list.html模板(tempalte)中將pagination.html模板(template)包含在{% content %}區塊(block)中,如下所示:

{% block content %}

{% include "pagination.html" with page=posts %}

{% endblock %}

我們傳遞給模板(template)的Page對象叫做posts,我們將分頁模板(tempalte)包含在帖子列模板(template)中指定參數來對它進行正確的渲染。這種方法你可以反復使用,用你的分頁模板(template)對不同的模型(models)視圖(views)進行分頁處理。


Paginator是如何工作的:

? ? 1.我們使用希望在每頁中顯示的對象的數量來實例化Paginator類。

? ? 2.我們獲取到page?GET參數來指明頁數

? ? 3.我們通過調用Paginatorpage()方法在期望的頁面中獲得了對象。

? ? 4.如果page參數不是一個整數,我們就返回第一頁的結果。如果這個參數數字超出了最大的頁數,我們就展示最后一頁的結果。

? ? 5.我們傳遞頁數并且獲取對象給這個模板(template)。


使用Django創建表單

Django提供了兩個可以創建表單的基本類:

????Form: 允許你創建一個標準表單

????ModelForm: 允許你創建一個可用于創建或者更新model實例的表單

is_valid()方法來驗證提交的數據。這個方法會驗證表單引進的數據,如果所有的字段都是有效數據,將會返回True。一旦有任何一個字段是無效的數據,is_valid()就會返回False。你可以通過訪問form.errors來查看所有驗證錯誤的列表。

如果表單數據驗證通過,我們通過訪問form.cleaned_data獲取驗證過的數據。這個屬性是一個表單字段和值的字典。


使用Django發送email

使用Django發送email非常簡單。首先,你需要有一個本地的SMTP服務或者通過在你項目的settings.py文件中添加以下設置去定義一個外部SMTP服務器的配置:

EMAIL_HOST: SMTP服務地址。默認本地。

EMAIL_POSR: SMATP服務端口,默認25。

EMAIL_HOST_USER: SMTP服務的用戶名。

EMAIL_HOST_PASSWORD: SMTP服務的密碼。

EMAIL_USE_TLS: 是否使用TLS加密連接。

EMAIL_USE_SSL: 是否使用隱式的SSL加密連接。

from django.core.mail import send_mail

send_mail()方法需要這些參數:郵件主題,內容,發送人以及一個收件人的列表。通過設置可選參數fail_silently=False,我們告訴這個方法如果email沒有發送成功那么需要拋出一個異常。

由于我們需要在email中包含帖子的超鏈接,所以我們通過使用post.get_absolute_url()方法來獲取到帖子的絕對路徑。我們將這個絕對路徑作為request.build_absolute_uri()的輸入值來構建一個完整的包含了HTTP schema和主機名的url。

post_url = request.build_absolute_url(post.get_absolute_url())


創建一個評論系統

{% with %}標簽(tag)允許我們分配一個值給新的變量,這個變量可以一直使用直到遇到{% endwith %}標簽(tag)。

{% with %}模板(template)標簽(tag)是非常有用的,可以避免直接操作數據庫或避免多次調用花費較多的方法。


創建自定義的模板標簽(template tags)和過濾器(filters)

當你需要在你的模板中添加功能而Django模板標簽(template tags)的核心設置無法提供此功能的時候,自定義模板標簽會非常方便。

創建自定義的模板標簽(template tags)

Django提供了以下幫助函數(functions)來允許你以一種簡單的方式創建自己的模板標簽(template tags):

simple_tag:處理數據并返回一個字符串(string)

inclusion_tag:處理數據并返回一個渲染過的模板(template)

assignment_tag:處理數據并在上下文(context)中設置一個變量(variable)

模板標簽(template tags)必須存在Django的應用中。

from django import template

register = template.Library()

from ..models import Post

@register.simple_tag

def total_posts():

????????return Post.published.count()

在使用自定義的模板標簽(template tags)之前,你必須使用{% load %}標簽在模板(template)中來加載它們才能有效。

@register.inclusion_tag('blog/post/latest_posts.html')

def show_latest_posts(count=5):

latest_posts = Post.published.order_by('-publish')[:count]

return {'latest_posts': latest_posts}

我們通過裝飾器@register.inclusion_tag注冊模板標簽(template tag),指定模板(template)必須被blog/post/latest_posts.html返回的值渲染

這個函數返回了一個字典變量而不是一個簡單的值。包含標簽(inclusion tags)必須返回一個字典值,作為上下文(context)來渲染特定的模板(template)。包含標簽(inclusion tags)返回一個字典。

@register.assignment_tag

def get_most_commented_posts(count=5):

return Post.published.annotate(

total_comments=Count('comments')

).order_by('-total_comments')[:count]

聚合了每一個帖子的評論總數并保存在total_comments字段中

過濾器其實就是Python函數并提供了一個或兩個參數————一個是需要處理的變量值,一個是可選的參數。它們返回的值可以被展示或者被別的過濾器(filters)處理。

from django.utils.safestring import mark_safe

import markdown

@register.filter(name='markdown')

def markdown_format(text):

return mark_safe(markdown.markdown(text))


為你的blog帖子創建feeds

Django有一個內置的syndication feed框架,可以動態(dynamically)生成RSS或者Atom feeds。

from django.contrib.syndication.views import Feed

from django.template.defaultfilters import truncatewords

from .models import Post

class LatestPostsFeed(Feed):

????????title = 'My blog'

????????link = '/blog/'

????????description = 'New posts of my blog.'

????????def ?items(self):

????????????????return Post.published.all()[:5]

????????def item_title(self, item):

????????????????return item.title

????????def item_description(self, item):

????????????????return ?truncatewords (item.body, 30)


手工渲染字段

{{ form.subject.errors }}

{{ form.subject.label_tag }}

{{ form.subject }}

{{form.non_field_errors}}查找每個字段的錯誤。

{{form.name_of_field.errors}}顯示表單錯誤的一個清單,并渲染成一個ul


widget

widgets用于指定Django在HTML的<input>元素的表現形式

設置weidget實例樣式 利用widget.attrs


save(commit=False)

save()方法接受一個commit的參數,其值為True或者False。默認為True。

如果你聲明 save(commit=False),那么它就會返回一個還未保存至數據庫的對象,這樣的話 你可以用這個對象添加一些額外的數據,然后在用save()保存到數據庫


自定義管理頁面

Django提供了admin.ModelAdmin類通過定義ModelAdmin的子類,來定義模型在Admin界面的顯示方式.

列表頁屬性

list_display:顯示字段,可以點擊列頭進行排序

list_filter:過濾字段,過濾框會出現在右側

search_fields:搜索字段,搜索框會出現在上側

list_per_page:分頁,分頁框會出現在下側


添加、修改頁屬性

fields:屬性的先后順序

fieldsets:屬性分組

fieldsets = [

? ? ? ('basic',{'fields': ['btitle']}),

? ? ? ('more', {'fields': ['bpub_date']}),

]


關聯對象

一對多的關系中,可以在一端的編輯頁面中編輯多端的對象,嵌入多端對象的方式包括表格、塊兩種。 類型InlineModelAdmin:表示在模型的編輯頁面嵌入關聯模型的編輯。子類TabularInline:以表格的形式嵌入。

子類StackedInline:以塊的形式嵌入。

1)打開booktest/admin.py文件,創建AreaStackedInline類。

class AreaStackedInline(admin.StackedInline):

? ? ?model=AreaInfo? ? #關聯子對象

? ? ?extra=2? ? #額外編輯2個子對象

2)打開booktest/admin.py文件,修改AreaAdmin類如下:

class? AreaAdmin(admin.ModelAdmin):

? ...

? ? inlines=[AreaStackedInline]


class AreaTabularInline(admin.TabularInline):

? ? ? model=AreaInfo? #關聯子對象

? ? ? extra=2? #額外編輯2個子對象


class? AreaAdmin(admin.ModelAdmin):

? ? ...

? ? inlines=[AreaTabularInline


布爾值的顯示

發布性別的顯示不是一個直觀的結果,可以使用方法進行封裝

def gender(self):

? ? if self.hgender:

? ? ? ?return '男'

? ?else:

? ? ? return '女'

gender.short_description = '性別'

在admin注冊中使用gender代替hgender

class HeroInfoAdmin(admin.ModelAdmin):

list_display = ['id', 'hname', 'gender', 'hcontent']

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容