日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python博客开发教程_Django 博客开发教程 12 - 评论

發(fā)布時(shí)間:2024/1/23 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python博客开发教程_Django 博客开发教程 12 - 评论 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

創(chuàng)建評(píng)論應(yīng)用

相對(duì)來(lái)說(shuō),評(píng)論其實(shí)是另外一個(gè)比較獨(dú)立的功能。Django 提倡,如果功能相對(duì)比較獨(dú)立的話,最好是創(chuàng)建一個(gè)應(yīng)用,把相應(yīng)的功能代碼寫到這個(gè)應(yīng)用里。我們的第一個(gè)應(yīng)用叫 blog,它里面放了展示博客文章列表和細(xì)節(jié)等相關(guān)功能的代碼。而這里我們?cè)賱?chuàng)建一個(gè)應(yīng)用,名為 comments,這里面將存放和評(píng)論功能相關(guān)的代碼。首先激活虛擬環(huán)境,然后輸入如下命令創(chuàng)建一個(gè)新的應(yīng)用:

python manage.py startapp comments

我們可以看到生成的 comments 應(yīng)用目錄結(jié)構(gòu)和 blog 應(yīng)用的目錄是類似的。關(guān)于創(chuàng)建應(yīng)用以及 Django 的目錄結(jié)構(gòu)在 建立 Django 博客應(yīng)用 中已經(jīng)有過(guò)介紹。創(chuàng)建新的應(yīng)用后一定要記得在 settings.py 里注冊(cè)這個(gè)應(yīng)用,Django 才知道這是一個(gè)應(yīng)用。

blogproject/settings.py

...

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'blog',

'comments', # 注冊(cè)新創(chuàng)建的 comments 應(yīng)用

]

...

設(shè)計(jì)評(píng)論的數(shù)據(jù)庫(kù)模型

用戶評(píng)論的數(shù)據(jù)必須被存儲(chǔ)到數(shù)據(jù)庫(kù)里,以便其他用戶訪問(wèn)時(shí) Django 能從數(shù)據(jù)庫(kù)取回這些數(shù)據(jù)然后展示給訪問(wèn)的用戶,因此我們需要為評(píng)論設(shè)計(jì)數(shù)據(jù)庫(kù)模型,這和設(shè)計(jì)文章、分類、標(biāo)簽的數(shù)據(jù)庫(kù)模型是一樣的,如果你忘了怎么做,再回顧一下 創(chuàng)建 Django 博客的數(shù)據(jù)庫(kù)模型 中的做法。我們的評(píng)論模型設(shè)計(jì)如下(評(píng)論模型的代碼寫在 commentmodels.py 里):

comments/models.py

from django.db import models

from django.utils.six import python_2_unicode_compatible

# python_2_unicode_compatible 裝飾器用于兼容 Python2

@python_2_unicode_compatible

class Comment(models.Model):

name = models.CharField(max_length=100)

email = models.EmailField(max_length=255)

url = models.URLField(blank=True)

text = models.TextField()

created_time = models.DateTimeField(auto_now_add=True)

post = models.ForeignKey('blog.Post')

def __str__(self):

return self.text[:20]

這里我們會(huì)保存評(píng)論用戶的 name(名字)、email(郵箱)、url(個(gè)人網(wǎng)站),用戶發(fā)表的內(nèi)容將存放在 text 字段里,created_time 記錄評(píng)論時(shí)間。最后,這個(gè)評(píng)論是關(guān)聯(lián)到某篇文章(Post)的,由于一個(gè)評(píng)論只能屬于一篇文章,一篇文章可以有多個(gè)評(píng)論,是一對(duì)多的關(guān)系,因此這里我們使用了 ForeignKey。關(guān)于 ForeKey 我們前面已有介紹,這里不再贅述。

同時(shí)注意我們?yōu)?DateTimeField 傳遞了一個(gè) auto_now_add=True 的參數(shù)值。auto_now_add 的作用是,當(dāng)評(píng)論數(shù)據(jù)保存到數(shù)據(jù)庫(kù)時(shí),自動(dòng)把 created_time 的值指定為當(dāng)前時(shí)間。created_time 記錄用戶發(fā)表評(píng)論的時(shí)間,我們肯定不希望用戶在發(fā)表評(píng)論時(shí)還得自己手動(dòng)填寫評(píng)論發(fā)表時(shí)間,這個(gè)時(shí)間應(yīng)該自動(dòng)生成。

創(chuàng)建了數(shù)據(jù)庫(kù)模型就要遷移數(shù)據(jù)庫(kù),遷移數(shù)據(jù)庫(kù)的命令也在前面講過(guò)。在虛擬環(huán)境下分別運(yùn)行下面兩條命令:

python manage.py makemigrations

python manage.py migrate

評(píng)論表單設(shè)計(jì)

這一節(jié)我們將學(xué)習(xí)一個(gè)全新的 Django 知識(shí):表單。那么什么是表單呢?基本的 HTML 知識(shí)告訴我們,在 HTML 文檔中這樣的代碼表示一個(gè)表單:

為什么需要表單呢?表單是用來(lái)收集并向服務(wù)器提交用戶輸入的數(shù)據(jù)的。考慮用戶在我們博客網(wǎng)站上發(fā)表評(píng)論的過(guò)程。當(dāng)用戶想要發(fā)表評(píng)論時(shí),他找到我們給他展示的一個(gè)評(píng)論表單(我們已經(jīng)看到在文章詳情頁(yè)的底部就有一個(gè)評(píng)論表單,你將看到表單呈現(xiàn)給我們的樣子),然后根據(jù)表單的要求填寫相應(yīng)的數(shù)據(jù)。之后用戶點(diǎn)擊評(píng)論按鈕,這些數(shù)據(jù)就會(huì)發(fā)送給某個(gè) URL。我們知道每一個(gè) URL 對(duì)應(yīng)著一個(gè) Django 的視圖函數(shù),于是 Django 調(diào)用這個(gè)視圖函數(shù),我們?cè)谝晥D函數(shù)中寫上處理用戶通過(guò)表單提交上來(lái)的數(shù)據(jù)的代碼,比如驗(yàn)證數(shù)據(jù)的合法性并且保存數(shù)據(jù)到數(shù)據(jù)庫(kù)中,那么用戶的評(píng)論就被 Django 后臺(tái)處理了。如果通過(guò)表單提交的數(shù)據(jù)存在錯(cuò)誤,那么我們把錯(cuò)誤信息返回給用戶,并在前端重新渲染,并要求用戶根據(jù)錯(cuò)誤信息修正表單中不符合格式的數(shù)據(jù),再重新提交。

Django 的表單功能就是幫我們完成上述所說(shuō)的表單處理邏輯,表單對(duì) Django 來(lái)說(shuō)是一個(gè)內(nèi)容豐富的話題,很難通過(guò)教程中的這么一個(gè)例子涵蓋其全部用法。因此我們強(qiáng)烈建議你在完成本教程后接下來(lái)的學(xué)習(xí)中仔細(xì)閱讀 Django 官方文檔關(guān)于 表單 的介紹,因?yàn)楸韱卧?Web 開發(fā)中會(huì)經(jīng)常遇到。

下面開始編寫評(píng)論表單代碼。在 comments 目錄下(和 models.py 同級(jí))新建一個(gè) forms.py 文件,用來(lái)存放表單代碼,我們的表單代碼如下:

comments/forms.py

from django import forms

from .models import Comment

class CommentForm(forms.ModelForm):

class Meta:

model = Comment

fields = ['name', 'email', 'url', 'text']

要使用 Django 的表單功能,我們首先導(dǎo)入 forms 模塊。Django 的表單類必須繼承自 forms.Form 類或者 forms.ModelForm 類。如果表單對(duì)應(yīng)有一個(gè)數(shù)據(jù)庫(kù)模型(例如這里的評(píng)論表單對(duì)應(yīng)著評(píng)論模型),那么使用 ModelForm 類會(huì)簡(jiǎn)單很多,這是 Django 為我們提供的方便。之后我們?cè)诒韱蔚膬?nèi)部類 Meta 里指定一些和表單相關(guān)的東西。model = Comment 表明這個(gè)表單對(duì)應(yīng)的數(shù)據(jù)庫(kù)模型是 Comment 類。fields = ['name', 'email', 'url', 'text'] 指定了表單需要顯示的字段,這里我們指定了 name、email、url、text 需要顯示。

關(guān)于表單進(jìn)一步的解釋

Django 為什么要給我們提供一個(gè)表單類呢?為了便于理解,我們可以把表單和前面講過(guò)的 Django ORM 系統(tǒng)做類比。回想一下,我們使用數(shù)據(jù)庫(kù)保存我們創(chuàng)建的博客文章,但是我們從頭到尾沒有寫過(guò)任何和數(shù)據(jù)庫(kù)有關(guān)的代碼(要知道數(shù)據(jù)庫(kù)自身也有一門數(shù)據(jù)庫(kù)語(yǔ)言),這是因?yàn)?Django 的 ORM 系統(tǒng)內(nèi)部幫我們做了一些事情。我們遵循 Django 的規(guī)范寫的一些 Python 代碼,例如創(chuàng)建 Post、Category 類,然后通過(guò)運(yùn)行數(shù)據(jù)庫(kù)遷移命令將這些代碼反應(yīng)到數(shù)據(jù)庫(kù)。

Django 的表單和這個(gè)思想類似,正常的前端表單代碼應(yīng)該是和本文開頭所提及的那樣,但是我們目前并沒有寫這些代碼,而是寫了一個(gè) CommentForm 這個(gè) Python 類。通過(guò)調(diào)用這個(gè)類的一些方法和屬性,Django 將自動(dòng)為我們創(chuàng)建常規(guī)的表單代碼,接下來(lái)的教程我們就會(huì)看到具體是怎么做的。

評(píng)論視圖函數(shù)

當(dāng)用戶提交表單中的數(shù)據(jù)后,Django 需要調(diào)用相應(yīng)的視圖函數(shù)來(lái)處理這些數(shù)據(jù),下面開始寫我們視圖函數(shù)處理邏輯:

comments/views.py

from django.shortcuts import render, get_object_or_404, redirect

from blog.models import Post

from .models import Comment

from .forms import CommentForm

def post_comment(request, post_pk):

# 先獲取被評(píng)論的文章,因?yàn)楹竺嫘枰言u(píng)論和被評(píng)論的文章關(guān)聯(lián)起來(lái)。

# 這里我們使用了 Django 提供的一個(gè)快捷函數(shù) get_object_or_404,

# 這個(gè)函數(shù)的作用是當(dāng)獲取的文章(Post)存在時(shí),則獲取;否則返回 404 頁(yè)面給用戶。

post = get_object_or_404(Post, pk=post_pk)

# HTTP 請(qǐng)求有 get 和 post 兩種,一般用戶通過(guò)表單提交數(shù)據(jù)都是通過(guò) post 請(qǐng)求,

# 因此只有當(dāng)用戶的請(qǐng)求為 post 時(shí)才需要處理表單數(shù)據(jù)。

if request.method == 'POST':

# 用戶提交的數(shù)據(jù)存在 request.POST 中,這是一個(gè)類字典對(duì)象。

# 我們利用這些數(shù)據(jù)構(gòu)造了 CommentForm 的實(shí)例,這樣 Django 的表單就生成了。

form = CommentForm(request.POST)

# 當(dāng)調(diào)用 form.is_valid() 方法時(shí),Django 自動(dòng)幫我們檢查表單的數(shù)據(jù)是否符合格式要求。

if form.is_valid():

# 檢查到數(shù)據(jù)是合法的,調(diào)用表單的 save 方法保存數(shù)據(jù)到數(shù)據(jù)庫(kù),

# commit=False 的作用是僅僅利用表單的數(shù)據(jù)生成 Comment 模型類的實(shí)例,但還不保存評(píng)論數(shù)據(jù)到數(shù)據(jù)庫(kù)。

comment = form.save(commit=False)

# 將評(píng)論和被評(píng)論的文章關(guān)聯(lián)起來(lái)。

comment.post = post

# 最終將評(píng)論數(shù)據(jù)保存進(jìn)數(shù)據(jù)庫(kù),調(diào)用模型實(shí)例的 save 方法

comment.save()

# 重定向到 post 的詳情頁(yè),實(shí)際上當(dāng) redirect 函數(shù)接收一個(gè)模型的實(shí)例時(shí),它會(huì)調(diào)用這個(gè)模型實(shí)例的 get_absolute_url 方法,

# 然后重定向到 get_absolute_url 方法返回的 URL。

return redirect(post)

else:

# 檢查到數(shù)據(jù)不合法,重新渲染詳情頁(yè),并且渲染表單的錯(cuò)誤。

# 因此我們傳了三個(gè)模板變量給 detail.html,

# 一個(gè)是文章(Post),一個(gè)是評(píng)論列表,一個(gè)是表單 form

# 注意這里我們用到了 post.comment_set.all() 方法,

# 這個(gè)用法有點(diǎn)類似于 Post.objects.all()

# 其作用是獲取這篇 post 下的的全部評(píng)論,

# 因?yàn)?Post 和 Comment 是 ForeignKey 關(guān)聯(lián)的,

# 因此使用 post.comment_set.all() 反向查詢?nèi)吭u(píng)論。

# 具體請(qǐng)看下面的講解。

comment_list = post.comment_set.all()

context = {'post': post,

'form': form,

'comment_list': comment_list

}

return render(request, 'blog/detail.html', context=context)

# 不是 post 請(qǐng)求,說(shuō)明用戶沒有提交數(shù)據(jù),重定向到文章詳情頁(yè)。

return redirect(post)

這個(gè)評(píng)論視圖相比之前的一些視圖復(fù)雜了很多,主要是處理評(píng)論的過(guò)程更加復(fù)雜。具體過(guò)程在代碼中已有詳細(xì)注釋,這里僅就視圖中出現(xiàn)了一些新的知識(shí)點(diǎn)進(jìn)行講解。

首先我們使用了 redirect 函數(shù)。這個(gè)函數(shù)位于 django.shortcuts 模塊中,它的作用是對(duì) HTTP 請(qǐng)求進(jìn)行重定向(即用戶訪問(wèn)的是某個(gè) URL,但由于某些原因,服務(wù)器會(huì)將用戶重定向到另外的 URL)。redirect 既可以接收一個(gè) URL 作為參數(shù),也可以接收一個(gè)模型的實(shí)例作為參數(shù)(例如這里的 post)。如果接收一個(gè)模型的實(shí)例,那么這個(gè)實(shí)例必須實(shí)現(xiàn)了 get_absolute_url 方法,這樣 redirect 會(huì)根據(jù) get_absolute_url 方法返回的 URL 值進(jìn)行重定向。

另外我們使用了 post.comment_set.all() 來(lái)獲取 post 對(duì)應(yīng)的全部評(píng)論。 Comment 和Post 是通過(guò) ForeignKey 關(guān)聯(lián)的,回顧一下我們當(dāng)初獲取某個(gè)分類 cate 下的全部文章時(shí)的代碼:Post.objects.filter(category=cate)。這里 post.comment_set.all() 也等價(jià)于 Comment.objects.filter(post=post),即根據(jù) post 來(lái)過(guò)濾該 post 下的全部評(píng)論。但既然我們已經(jīng)有了一個(gè) Post 模型的實(shí)例 post(它對(duì)應(yīng)的是 Post 在數(shù)據(jù)庫(kù)中的一條記錄),那么獲取和 post 關(guān)聯(lián)的評(píng)論列表有一個(gè)簡(jiǎn)單方法,即調(diào)用它的 xxx_set 屬性來(lái)獲取一個(gè)類似于 objects 的模型管理器,然后調(diào)用其 all 方法來(lái)返回這個(gè) post 關(guān)聯(lián)的全部評(píng)論。 其中 xxx_set 中的 xxx 為關(guān)聯(lián)模型的類名(小寫)。例如 Post.objects.filter(category=cate) 也可以等價(jià)寫為 cate.post_set.all()。

綁定 URL

視圖函數(shù)需要和 URL 綁定,這里我們?cè)?comment 應(yīng)用中再建一個(gè) urls.py 文件,寫上 URL 模式:

comments/urls.py

from django.conf.urls import url

from . import views

app_name = 'comments'

urlpatterns = [

url(r'^comment/post/(?P[0-9]+)/$', views.post_comment, name='post_comment'),

]

別忘了給這個(gè)評(píng)論的 URL 模式規(guī)定命名空間,即 app_name = 'comments'。

最后要在項(xiàng)目的 blogprokect 目錄的 urls.py 里包含 commentsurls.py 這個(gè)文件:

blogproject/urls.py

urlpatterns = [

url(r'^admin/', admin.site.urls),

url(r'', include('blog.urls')),

+ url(r'', include('comments.urls')),

]

更新文章詳情頁(yè)面的視圖函數(shù)

我們可以看到評(píng)論表單和評(píng)論列表是位于文章詳情頁(yè)面的,處理文章詳情頁(yè)面的視圖函數(shù)是 detail,相應(yīng)地需要更新 detail,讓它生成表單和從數(shù)據(jù)庫(kù)獲取文章對(duì)應(yīng)的評(píng)論列表數(shù)據(jù),然后傳遞給模板顯示:

blog/views.py

import markdown

from django.shortcuts import render, get_object_or_404

+ from comments.forms import CommentForm

from .models import Post, Category

def detail(request, pk):

post = get_object_or_404(Post, pk=pk)

post.body = markdown.markdown(post.body,

extensions=[

'markdown.extensions.extra',

'markdown.extensions.codehilite',

'markdown.extensions.toc',

])

# 記得在頂部導(dǎo)入 CommentForm

form = CommentForm()

# 獲取這篇 post 下的全部評(píng)論

comment_list = post.comment_set.all()

# 將文章、表單、以及文章下的評(píng)論列表作為模板變量傳給 detail.html 模板,以便渲染相應(yīng)數(shù)據(jù)。

context = {'post': post,

'form': form,

'comment_list': comment_list

}

return render(request, 'blog/detail.html', context=context)

在前端渲染表單

使用 Django 表單的一個(gè)好處就是 Django 能幫我們自動(dòng)渲染表單。我們?cè)诒韱蔚囊晥D函數(shù)里傳遞了一個(gè) form 變量給模板,這個(gè)變量就包含了自動(dòng)生成 HTML 表單的全部數(shù)據(jù)。在 detail.html 中通過(guò) form 來(lái)自動(dòng)生成表單。刪掉原來(lái)用于占位的 HTML 評(píng)論表單代碼,即下面這段代碼:

名字:

...

替換成如下的代碼:

{% csrf_token %}

名字:

{{ form.name }}

{{ form.name.errors }}

郵箱:

{{ form.email }}

{{ form.email.errors }}

URL:

{{ form.url }}

{{ form.url.errors }}

評(píng)論:

{{ form.text }}

{{ form.text.errors }}

發(fā)表

{{ form.name }}、{{ form.email }}、{{ form.url }} 等將自動(dòng)渲染成表單控件,例如 控件。

{{ form.name.errors }}、{{ form.email.errors }} 等將渲染表單對(duì)應(yīng)字段的錯(cuò)誤(如果有的話),例如用戶 email 格式填錯(cuò)了,那么 Django 會(huì)檢查用戶提交的 email 的格式,然后將格式錯(cuò)誤信息保存到 errors 中,模板便將錯(cuò)誤信息渲染顯示。

顯示評(píng)論內(nèi)容

在 detail 視圖函數(shù)我們獲取了全部評(píng)論數(shù)據(jù),并通過(guò) comment_list 傳遞給了模板。和處理 index 頁(yè)面的文章列表方式是一樣的,我們?cè)谀0逯型ㄟ^(guò) {% for %} 模板標(biāo)簽來(lái)循環(huán)顯示文章對(duì)應(yīng)的全部評(píng)論內(nèi)容。

刪掉占位用的評(píng)論內(nèi)容的 HTML 代碼,即如下的代碼:

  • 追夢(mèng)人物

    2017年3月12日 14:56

    文章觀點(diǎn)又有道理又符合人性,這才是真正為了表達(dá)觀點(diǎn)而寫,不是為了迎合某某知名人士粉絲而寫。我覺得如果瓊瑤是前妻,生了三孩子后被一不知名的女人挖了墻角,我不信誰(shuí)會(huì)說(shuō)那個(gè)女人是追求真愛,說(shuō)同情瓊瑤罵小三的女人都是弱者。

...

替換成如下的代碼:

{% for comment in comment_list %}

{{ comment.name }}

{{ comment.created_time }}

{{ comment.text }}

{% empty %}

暫無(wú)評(píng)論

{% endfor %}

接下來(lái)嘗試在詳情頁(yè)下的評(píng)論表單提交一些評(píng)論數(shù)據(jù),可以看到詳情頁(yè)的評(píng)論列表處渲染了你提交的評(píng)論數(shù)據(jù)。

總結(jié)

本章節(jié)的代碼位于:Step12: comments。

如果遇到問(wèn)題,請(qǐng)通過(guò)下面的方式尋求幫助。

在 評(píng)論 - 追夢(mèng)人物的博客 的評(píng)論區(qū)留言。

將問(wèn)題的詳細(xì)描述通過(guò)郵件發(fā)送到 djangostudyteam@163.com,一般會(huì)在 24 小時(shí)內(nèi)回復(fù)。

更多Django 教程,請(qǐng)?jiān)L問(wèn) 追夢(mèng)人物的博客。

總結(jié)

以上是生活随笔為你收集整理的python博客开发教程_Django 博客开发教程 12 - 评论的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。