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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

python个人网站开发_python 全栈开发,Day81(博客系统个人主页,文章详情页)

發(fā)布時間:2023/11/27 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python个人网站开发_python 全栈开发,Day81(博客系统个人主页,文章详情页) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、個人主頁

隨筆分類

需求:查詢當(dāng)前站點每一個分類的名稱以及對應(yīng)的文章數(shù)

完成這個需求,就可以展示左側(cè)的分類

它需要利用分組查詢,那么必須要會基于雙下劃線的查詢。

基于雙下劃線的查詢,簡單來講,就是用join。將多個表拼接成一張表,那么就可以單表操作了!

表關(guān)系圖

圖中箭頭開始的英文字母表示關(guān)聯(lián)字段

按照箭頭方向查詢,表示正向查詢,否則為反向查詢

分解步驟:

先來查詢每一個分類的名稱以及對應(yīng)的文章數(shù)

看上面的關(guān)系圖,以Category表為基礎(chǔ)表來查詢Article表對應(yīng)的文章數(shù),需要用到反向查詢。

記住一個原則,正向查詢使用字段,反向查詢使用表名

修改views.py,導(dǎo)入相關(guān)表和聚合函數(shù)

from django.shortcuts importrender,HttpResponse,redirectfrom django.contrib importauthfrom blog.models importArticle,UserInfo,Blog,Category,Tagfrom django.db.models importSum,Avg,Max,Min,Count#Create your views here.

deflogin(request):if request.method=="POST":

user=request.POST.get("user")

pwd=request.POST.get("pwd")#用戶驗證成功,返回user對象,否則返回None

user=auth.authenticate(username=user,password=pwd)ifuser:#登錄,注冊session

#全局變量 request.user=當(dāng)前登陸對象(session中)

auth.login(request,user)return redirect("/index/")return render(request,"login.html")defindex(request):

article_list=Article.objects.all()return render(request,"index.html",{"article_list":article_list})def logout(request): #注銷

auth.logout(request)return redirect("/index/")defhomesite(request,username):"""查詢

:param request:

:param username:

:return:"""

#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blog#查詢當(dāng)前用戶發(fā)布的所有文章

article_list=Article.objects.filter(user__username=username)

ret= Category.objects.values("pk").annotate(c=Count("article__title")).values("title","c")print(ret)

dict= {"blog":blog,"article_list":article_list,

}return render(request,"homesite.html",dict)

View Code

解釋:

pk表示主鍵

上面這句sql表示以Category表id來分組,得到分類名以及統(tǒng)計數(shù)

多添加幾篇文章,給另外一個用戶也添加幾篇文章

訪問個人站點:http://127.0.0.1:8000/xiao/

查看Pycharm控制臺輸出:

上面得到了所有文章的分類以及文章數(shù)。

再來查詢當(dāng)前站點每一個分類的名稱以及對應(yīng)的文章數(shù)

思路:只需要對Category表進(jìn)行篩選,過濾中當(dāng)前站點用戶的分類

在homesite視圖函數(shù)中,已經(jīng)有一個當(dāng)前站點的blog對象。

在Category模型表中,有一個blog屬性,它和blog是一對多關(guān)系。那么只需要blog=blog,就可以了

修改視圖函數(shù)homesite的ret變量

ret = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values("title","c")

注意:等式左邊的blog表示Category模型表的blog屬性,實際上就是blog_id字段

等式右邊的是blog變量,它是一個model對象。那么blog=blog,就可以查詢出,當(dāng)前站點的分類了!

刷新網(wǎng)頁,查看Pycharm控制臺輸出:

既然結(jié)果出來了,模板就可以渲染了

修改homesite視圖函數(shù),完整代碼如下:

from django.shortcuts importrender,HttpResponse,redirectfrom django.contrib importauthfrom blog.models importArticle,UserInfo,Blog,Category,Tagfrom django.db.models importSum,Avg,Max,Min,Count#Create your views here.

deflogin(request):if request.method=="POST":

user=request.POST.get("user")

pwd=request.POST.get("pwd")#用戶驗證成功,返回user對象,否則返回None

user=auth.authenticate(username=user,password=pwd)ifuser:#登錄,注冊session

#全局變量 request.user=當(dāng)前登陸對象(session中)

auth.login(request,user)return redirect("/index/")return render(request,"login.html")defindex(request):

article_list=Article.objects.all()return render(request,"index.html",{"article_list":article_list})def logout(request): #注銷

auth.logout(request)return redirect("/index/")defhomesite(request,username):"""查詢

:param request:

:param username:

:return:"""

#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blogprint(blog,type(blog))#查詢當(dāng)前用戶發(fā)布的所有文章

article_list=Article.objects.filter(user__username=username)

cate_list= Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(cate_list)

dict= {"blog":blog,"article_list":article_list,"cate_list":cate_list

}return render(request,"homesite.html",dict)

View Code

修改homesite.html

Title

*{

margin: 0;

padding: 0;

}

.header {

width:100%;

height: 59px;

background-color: #369;

}

.header .title {

line-height: 59px;

color: white;

font-weight: lighter;

margin-left: 20px;

font-size: 18px;

}

.left_region {

margin-top: 10px;

}

.info {

margin-top: 10px;

color: darkgray;

}

h5 a {

color:#105cb6;

font-size: 14px;

font-weight: bold;

text-decoration: underline;

}

{{ blog.title }}

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

Panel content

日期歸檔

Panel content{% for article in article_list %}
{{ article.title }}

{{ article.desc }}

發(fā)布于{{ article.create_time|date:'Y-m-d H:i' }}??

href="">評論({{ article.comment_count }})

點贊({{ article.up_count }})
{% endfor %}

View Code

values_list返回的是一個元組,所以模板中,直接用cate.0就可以取到分類名

刷新網(wǎng)頁,效果如下:

我的標(biāo)簽

我的標(biāo)簽和隨筆的查詢語句是類似的,換一個表名,就可以了!

先在admin后臺為不同的用戶,添加標(biāo)簽

由于admin后臺無法直接將博客表和標(biāo)簽表做對應(yīng)關(guān)系,所以只能手動綁定關(guān)系。

使用navicat打開blog_article2tag表

注意:以實際情況為準(zhǔn)

修改homesite視圖函數(shù),查詢我的標(biāo)簽

defhomesite(request,username):"""查詢

:param request:

:param username:

:return:"""

#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blogprint(blog,type(blog))#查詢當(dāng)前用戶發(fā)布的所有文章

article_list=Article.objects.filter(user__username=username)#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(cate_list)#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(tag_list)

dict= {"blog":blog,"article_list":article_list,"cate_list":cate_list,"tag_list":tag_list,

}return render(request,"homesite.html",dict)

View Code

刷新網(wǎng)頁,查看Pycharm控制臺

修改homesite.html,開始渲染網(wǎng)頁

Title

*{

margin: 0;

padding: 0;

}

.header {

width:100%;

height: 59px;

background-color: #369;

}

.header .title {

line-height: 59px;

color: white;

font-weight: lighter;

margin-left: 20px;

font-size: 18px;

}

.left_region {

margin-top: 10px;

}

.info {

margin-top: 10px;

color: darkgray;

}

h5 a {

color:#105cb6;

font-size: 14px;

font-weight: bold;

text-decoration: underline;

}

{{ blog.title }}

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

{% for tag in tag_list %}

{{ tag.0 }}({{ tag.1 }})

{% endfor %}

日期歸檔

Panel content{% for article in article_list %}
{{ article.title }}

{{ article.desc }}

發(fā)布于{{ article.create_time|date:'Y-m-d H:i' }}??

href="">評論({{ article.comment_count }})

點贊({{ article.up_count }})
{% endfor %}

View Code

刷新網(wǎng)頁,效果如下:

注意:如果網(wǎng)頁數(shù)據(jù)沒有展示,請一定要查看數(shù)據(jù)庫是否有對應(yīng)的記錄!

日期歸檔

查看Article表的create_time字段

注意:它的時間后面,有很多小數(shù)點。每一條是不一樣的,所以不能直接分組,否則沒有意義!

要實現(xiàn)這個功能,有3個小知識點:

1.dateformat

2.extra

3.單表分組查詢

dateformat

DATE_FORMAT() 函數(shù)用于以不同的格式顯示日期/時間數(shù)據(jù)。

每個數(shù)據(jù)庫都有日期/時間 處理的函數(shù),在MySQL中,叫dateformat。SQLite中,叫strftime

舉例:

#截取年月日

mysql> select date_format("2018-07-11 06:39:07",'%Y-%m-%d') as date;+------------+

| date |

+------------+

| 2018-07-11 |

+------------+

1 row in set (0.00sec)#截取年月

mysql> select date_format("2018-07-11 06:39:07",'%Y-%m') as date;+---------+

| date |

+---------+

| 2018-07 |

+---------+

1 row in set (0.00 sec)

View Code

extra

有些情況下,Django的查詢語法難以表達(dá)復(fù)雜的where子句,對于這種情況, Django 提供了extra()QuerySet修改機(jī)制 。它能在QuerySet生成的SQL從句中注入新子句,extra可以指定一個或多個參數(shù),例如select、where或tables。 這些參數(shù)都不是必須的,但是至少要使用一個。

語法:

extra(select=None, where=None, params=None,

tables=None, order_by=None, select_params=None)

select參數(shù)

select參數(shù)可以在select從句中添加其他字段信息,它應(yīng)該是一個字典,存放著屬性名到 SQL 從句的映射。

舉例:

修改homesite視圖函數(shù),增加幾行代碼

defhomesite(request,username):"""查詢

:param request:

:param username:

:return:"""

#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blogprint(blog,type(blog))#查詢當(dāng)前用戶發(fā)布的所有文章

article_list=Article.objects.filter(user__username=username)#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(cate_list)#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(tag_list)#測試日期

test_date = Article.objects.filter(comment_count=0).extra(select={'y_m_date': "create_time > '2017-09-05'"})print(test_date)for i intest_date:print(i.y_m_date)

dict= {"blog":blog,"article_list":article_list,"cate_list":cate_list,"tag_list":tag_list,

}return render(request,"homesite.html",dict)

View Code

大概意思就是,查詢創(chuàng)建時間大于2017-09-05的記錄

刷新網(wǎng)頁,查看Pycharm控制臺輸出:

1

1

1

如果條件成立,返回1。否則返回0

需要注意的是:此時已經(jīng)給Article表增加一個臨時字段y_m_date。它在內(nèi)存中,每次使用extra查詢才會存在!

單表分組查詢

查詢當(dāng)前用戶的所有文章,根據(jù)日期歸檔

defhomesite(request,username):"""查詢

:param request:

:param username:

:return:"""

#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blogprint(blog,type(blog))#查詢當(dāng)前用戶發(fā)布的所有文章

article_list=Article.objects.filter(user__username=username)#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(cate_list)#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")print(tag_list)#日期歸檔

date_list = Article.objects.filter(user=user).extra(select={"y_m_date": "strftime('%%Y/%%m',create_time)"}).values("y_m_date").annotate(c=Count("title")).values_list("y_m_date", "c")print(date_list)

dict= {"blog":blog,"article_list":article_list,"cate_list":cate_list,"tag_list":tag_list,"date_list":date_list,

}return render(request,"homesite.html",dict)

View Code

解釋:

SQLite的日期格式化使用strftime,它使用2個%號來區(qū)分。

user=user? 等式左邊的user是Article模型表的user屬性,也就是user_id。等式右邊的user是UserInfo表的model對象!

刷新頁面,查看Pychram控制臺輸出:

修改homesite.html,開始渲染網(wǎng)頁

Title

*{

margin: 0;

padding: 0;

}

.header {

width:100%;

height: 59px;

background-color: #369;

}

.header .title {

line-height: 59px;

color: white;

font-weight: lighter;

margin-left: 20px;

font-size: 18px;

}

.left_region {

margin-top: 10px;

}

.info {

margin-top: 10px;

color: darkgray;

}

h5 a {

color:#105cb6;

font-size: 14px;

font-weight: bold;

text-decoration: underline;

}

{{ blog.title }}

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

{% for tag in tag_list %}

{{ tag.0 }}({{ tag.1 }})

{% endfor %}

日期歸檔

{% for date in date_list %}

{{ date.0 }}({{ date.1 }})

{% endfor %}{% for article in article_list %}
{{ article.title }}

{{ article.desc }}

發(fā)布于{{ article.create_time|date:'Y-m-d H:i' }}??

href="">評論({{ article.comment_count }})

點贊({{ article.up_count }})
{% endfor %}

View Code

刷新網(wǎng)頁,效果如下:

左側(cè)面板添加鏈接

接下來,需要點擊左邊的分類、標(biāo)簽、歸檔,顯示相關(guān)的文章

訪問博客園左側(cè)的分類、標(biāo)簽、歸檔,方法它有一個規(guī)律

標(biāo)簽:

http://www.cnblogs.com/用戶名/tag/標(biāo)簽名/

分類:

https://www.cnblogs.com/用戶名/category/分類id.html

歸檔:

https://www.cnblogs.com/用戶名/archive/年/月.html

修改urls.py,增加3個路徑。注意要導(dǎo)入re_path模塊

re_path('(?P\w+)/category/(?P.*)', views.homesite),

re_path('(?P\w+)/tag/(?P.*)', views.homesite),

re_path('(?P\w+)/achrive/(?P.*)', views.homesite),

仔細(xì)觀察個人站點網(wǎng)頁的布局

發(fā)現(xiàn),點擊不同的分類、標(biāo)簽、歸檔。紅色區(qū)域和綠色區(qū)域始終不變,只有紫色區(qū)域在變動。變動區(qū)域取決于article_list變量!

那么個人站點首頁、分類、標(biāo)簽、歸檔這4種url可以共用一個視圖函數(shù)homesite模板以及視圖函數(shù)。

重新修改urls.py,完整代碼如下:

from django.contrib importadminfrom django.urls importpath,re_pathfrom blog importviews

urlpatterns=[

path('admin/', admin.site.urls),

path('login/', views.login),

path('index/', views.index),

path('logout/', views.logout),

path('', views.index),#跳轉(zhuǎn)

re_path('(?P\w+)/(?Pcategory|tag|achrive)/(?P.*)/$', views.homesite),#個人站點

re_path('(?P\w+)/$', views.homesite),

]

View Code

那么問題來了,訪問個人站點時,不需要額外的參數(shù)。

訪問分類/標(biāo)簽/歸檔 這2個類別是,必須要2個額外的變量。分別是類別、類別參數(shù)。

homesite視圖函數(shù),如果分別接收呢?答案是,使用**kwargs,它可以接收可變的關(guān)鍵字參數(shù),至少1個或者多個參數(shù)!

修改homesite.html,增加一個網(wǎng)頁圖標(biāo),否則待會測試時,會有2次請求。

如果網(wǎng)頁沒有圖標(biāo),每次會請求一次網(wǎng)絡(luò)請求,請求favicon.ico

在title標(biāo)簽下面,增加一行

修改homesite視圖函數(shù)

def homesite(request,username,**kwargs):"""查詢

:param request:

:param username:

:return:"""

print("kwargs", kwargs)#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blog#查詢當(dāng)前用戶發(fā)布的所有文章

article_list=Article.objects.filter(user__username=username)#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(cate_list)

#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(tag_list)

#日期歸檔

date_list = Article.objects.filter(user=user).extra(select={"y_m_date": "strftime('%%Y/%%m',create_time)"}).values("y_m_date").annotate(c=Count("title")).values_list("y_m_date", "c")#print(date_list)

dict= {"blog":blog,"article_list":article_list,"cate_list":cate_list,"tag_list":tag_list,"date_list":date_list,

}return render(request,"homesite.html",dict)

View Code

訪問個人站點:?http://127.0.0.1:8000/xiao/

Pycharm控制臺輸出:kwargs {}

訪問個人分類python:?http://127.0.0.1:8000/xiao/category/python/

Pycharm控制臺輸出:kwargs {'params': 'python/', 'condition': 'category'}

訪問個人標(biāo)簽:?http://127.0.0.1:8000/xiao/tag/python全棧/

Pycharm控制臺輸出:kwargs {'params': 'python全棧/', 'condition': 'tag'}

訪問個人歸檔:?http://127.0.0.1:8000/xiao/achrive/2018/07

Pycharm控制臺輸出:kwargs {'params': '2018/07', 'condition': 'achrive'}

注意:要帶上用戶名,否則出現(xiàn)404錯誤

那么,只需要判斷kwargs變量,就可以區(qū)分了!

修改homesite視圖函數(shù)

def homesite(request,username,**kwargs):"""查詢

:param request:

:param username:

:return:"""

print("kwargs", kwargs)#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blog#查詢當(dāng)前用戶發(fā)布的所有文章

if notkwargs:

article_list= Article.objects.filter(user__username=username)else:

condition= kwargs.get("condition")

params= kwargs.get("params")#判斷分類、隨筆、歸檔

if condition == "category":

article_list= Article.objects.filter(user__username=username).filter(category__title=params)elif condition == "tag":

article_list= Article.objects.filter(user__username=username).filter(tags__title=params)else:

year, month= params.split("/")

article_list= Article.objects.filter(user__username=username).filter(create_time__year=year,

create_time__month=month)#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(cate_list)

#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(tag_list)

#日期歸檔

date_list = Article.objects.filter(user=user).extra(select={"y_m_date": "strftime('%%Y/%%m',create_time)"}).values("y_m_date").annotate(c=Count("title")).values_list("y_m_date", "c")#print(date_list)

dict= {"blog":blog,"article_list":article_list,"cate_list":cate_list,"tag_list":tag_list,"date_list":date_list,"username":username,

}return render(request,"homesite.html",dict)

View Code

修改homesite.html

Title

*{

margin: 0;

padding: 0;

}

.header {

width:100%;

height: 59px;

background-color: #369;

}

.header .title {

line-height: 59px;

color: white;

font-weight: lighter;

margin-left: 20px;

font-size: 18px;

}

.left_region {

margin-top: 10px;

}

.info {

margin-top: 10px;

color: darkgray;

}

h5 a {

color:#105cb6;

font-size: 14px;

font-weight: bold;

text-decoration: underline;

}

{{ blog.title }}

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

{% for tag in tag_list %}

{{ tag.0 }}({{ tag.1 }})

{% endfor %}

日期歸檔

{% for date in date_list %}

{{ date.0 }}({{ date.1 }})

{% endfor %}{% for article in article_list %}
{{ article.title }}

{{ article.desc }}

發(fā)布于{{ article.create_time|date:'Y-m-d H:i' }}??

href="">評論({{ article.comment_count }})

點贊({{ article.up_count }})
{% endfor %}

View Code

訪問個人站點:http://127.0.0.1:8000/xiao/

效果如下:

主題切換

查看blog_blog表,有2條記錄

theme對應(yīng)主題的css文件

在homesite.html中的style標(biāo)簽定義了一些樣式。現(xiàn)在需要分離出來!

每一個用戶有自己的標(biāo)題顏色,比如xiao用默認(rèn)的藍(lán)色,zhang用綠色

在static中新建css目錄,在css中新建文件夾theme,新建3個css文件,其中common.css是公共樣式!

common.css

*{

margin: 0;

padding: 0;

}

.header {

width:100%;

height: 59px;

background-color: #369;

}

.header .title {

line-height: 59px;

color: white;

font-weight: lighter;

margin-left: 20px;

font-size: 18px;

}

.left_region {

margin-top: 10px;

}

.info {

margin-top: 10px;

color: darkgray;

}

h5 a {

color:#105cb6;

font-size: 14px;

font-weight: bold;

text-decoration: underline;

}

View Code

xiao.css

.header {

width:100%;

height: 59px;

background-color: #369;

}

View Code

zhang.css

.header {

width:100%;

height: 59px;

background-color: green;

}

View Code

修改homesite.html,修改head部分,完整代碼如下:

Title

{#公共樣式#}

{#個人站點主題樣式#}

{{ blog.title }}

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

{% for tag in tag_list %}

{{ tag.0 }}({{ tag.1 }})

{% endfor %}

日期歸檔

{% for date in date_list %}

{{ date.0 }}({{ date.1 }})

{% endfor %}{% for article in article_list %}
{{ article.title }}

{{ article.desc }}

發(fā)布于{{ article.create_time|date:'Y-m-d H:i' }}??

href="">評論({{ article.comment_count }})

點贊({{ article.up_count }})
{% endfor %}

View Code

使用谷歌瀏覽器登錄xiao的用戶,進(jìn)入個人主頁

使用火狐瀏覽器登錄zhang的用戶

進(jìn)入個人主頁,發(fā)現(xiàn)標(biāo)題顏色沒有換過來

進(jìn)入admin后臺,點擊users表,找到zhang用戶,發(fā)現(xiàn)它沒有綁定個人站點。

因為使用命令創(chuàng)建用戶時,blog_id字段,默認(rèn)為空!

手動綁定一下

再次刷新頁面,效果如下:

文章詳情

由于文章詳情頁,功能繁多,必須專門做一個視圖才行。

修改urls.py,增加路徑article_detail

urlpatterns =[

path('admin/', admin.site.urls),

path('login/', views.login),

path('index/', views.index),

path('logout/', views.logout),

path('', views.index),#文章詳情

re_path('(?P\w+)/articles/(?P\d+)/$', views.article_detail),#跳轉(zhuǎn)

re_path('(?P\w+)/(?Pcategory|tag|achrive)/(?P.*)/$', views.homesite),#個人站點

re_path('(?P\w+)/$', views.homesite),

]

View Code

由于文章詳情頁的左測和標(biāo)題部分是通用的,需要用到模板繼承

模板繼承

新建base.html,將homesite.html的代碼復(fù)制過來,刪除多余的部分。增加block

Title{#公共樣式#}

{#個人站點主題樣式#}

{#bootstrap#}

{{ blog.title }}

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

{% for tag in tag_list %}

{{ tag.0 }}({{ tag.1 }})

{% endfor %}

日期歸檔

{% for date in date_list %}

{{ date.0 }}({{ date.1 }})

{% endfor %}{% block content %}

{% endblock %}

View Code

修改homesite.html

{% extends "base.html" %}

{% block content %}

{% for article in article_list %}
{{ article.title }}

{{ article.desc }}

發(fā)布于{{ article.create_time|date:'Y-m-d H:i' }}??評論({{ article.comment_count }})??點贊({{ article.up_count }})
{% endfor %}{% endblock %}

View Code

增加article_detail.html

{% extends "base.html" %}

{% block content %}

{{ article_obj.title }}

{{ article_obj.content }}{% endblock %}

View Code

修改article_detail視圖函數(shù)

defarticle_detail(request,username,article_id):

user= UserInfo.objects.filter(username=username).first()#查詢當(dāng)前站點對象

blog =user.blog#查詢指定id的文章

article_obj=Article.objects.filter(pk=article_id).first()#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(cate_list)

#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(tag_list)

#日期歸檔

date_list = Article.objects.filter(user=user).extra(select={"y_m_date": "strftime('%%Y/%%m',create_time)"}).values("y_m_date").annotate(c=Count("title")).values_list("y_m_date", "c")#print(date_list)

dict= {"blog": blog,"article_obj": article_obj,"cate_list": cate_list,"tag_list": tag_list,"date_list": date_list,"username": username,

}return render(request,'article_detail.html',dict)

View Code

刷新網(wǎng)頁,點擊左側(cè)的一個分類,效果如下:

點擊右邊的一篇文章

關(guān)于內(nèi)容部分,為什么是html標(biāo)簽。這些暫時不處理,后面會講到如何處理!

查看article_detail和homesite 這2個視圖函數(shù),有重復(fù)的代碼。在編程的過程中,最好不要出現(xiàn)重復(fù)代碼,怎么辦呢?使用函數(shù)封裝!

函數(shù)封裝

修改views.py,增加函數(shù)get_query_data。刪掉article_detail和homesite 這2個視圖函數(shù)中的重復(fù)代碼,完整代碼如下:

from django.shortcuts importrender,HttpResponse,redirectfrom django.contrib importauthfrom blog.models importArticle,UserInfo,Blog,Category,Tagfrom django.db.models importSum,Avg,Max,Min,Count#Create your views here.

deflogin(request):if request.method=="POST":

user=request.POST.get("user")

pwd=request.POST.get("pwd")#用戶驗證成功,返回user對象,否則返回None

user=auth.authenticate(username=user,password=pwd)ifuser:#登錄,注冊session

#全局變量 request.user=當(dāng)前登陸對象(session中)

auth.login(request,user)return redirect("/index/")return render(request,"login.html")defindex(request):

article_list=Article.objects.all()return render(request,"index.html",{"article_list":article_list})def logout(request): #注銷

auth.logout(request)return redirect("/index/")defget_query_data(request,username):

user= UserInfo.objects.filter(username=username).first()#查詢當(dāng)前站點對象

blog =user.blog#隨筆分類

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(cate_list)

#我的標(biāo)簽

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(tag_list)

#日期歸檔

date_list = Article.objects.filter(user=user).extra(select={"y_m_date": "strftime('%%Y/%%m',create_time)"}).values("y_m_date").annotate(c=Count("title")).values_list("y_m_date", "c")#print(date_list)

dict= {"blog": blog,"cate_list": cate_list,"tag_list": tag_list,"date_list": date_list,"username": username,

}return dict #返回字典

def homesite(request,username,**kwargs):"""查詢

:param request:

:param username:

:return:"""

print("kwargs", kwargs)#查詢當(dāng)前站點的用戶對象

user=UserInfo.objects.filter(username=username).first()if notuser:return render(request,"not_found.html")#查詢當(dāng)前站點對象

blog=user.blog#查詢當(dāng)前用戶發(fā)布的所有文章

if notkwargs:

article_list= Article.objects.filter(user__username=username)else:

condition= kwargs.get("condition")

params= kwargs.get("params")#判斷分類、隨筆、歸檔

if condition == "category":

article_list= Article.objects.filter(user__username=username).filter(category__title=params)elif condition == "tag":

article_list= Article.objects.filter(user__username=username).filter(tags__title=params)else:

year, month= params.split("/")

article_list= Article.objects.filter(user__username=username).filter(create_time__year=year,

create_time__month=month)

dict= get_query_data(request,username) #調(diào)用函數(shù)

dict['article_list'] = article_list #增加一個key

return render(request,"homesite.html",dict)defarticle_detail(request,username,article_id):

content_text= get_query_data(request,username) #調(diào)用函數(shù)

#查詢指定id的文章

article_obj = Article.objects.filter(pk=article_id).first()

content_text['article_obj'] = article_obj #增加一個key

return render(request,'article_detail.html',content_text)

View Code

注意:get_query_data必須要在2個視圖函數(shù)的上面,否則無法調(diào)用!

重新訪問網(wǎng)頁,效果如下:

封裝函數(shù),有一個局限性,如果新增變量,需要增加字典key-value。由于繼承模板時,變量是不會繼承的。所以引用的視圖函數(shù),必須重新傳值才可以渲染。那么可不可以,將模板和數(shù)據(jù)包裝成一個模板,作為一個整體。其他模板繼承時,就是一個已經(jīng)渲染過的模板呢?

答案是有的,那就是inclusion_tag

包含標(biāo)簽(Inclusion tags)

Django過濾器和標(biāo)簽功能很強(qiáng)大,而且支持自定義標(biāo)簽,很是方便;其中一種標(biāo)簽是Inclusion tags,即包含標(biāo)簽

包含標(biāo)簽(Inclusion tags)通過渲染其他的模板來展示內(nèi)容,這類標(biāo)簽的用途在于一些相似的內(nèi)容的展示,并且返回的內(nèi)容是渲染其他模板得到的內(nèi)容。

自定義標(biāo)簽必須在應(yīng)用名目錄下創(chuàng)建templatetags目錄。注意:此目錄名必須叫這個名字,不可改變。

在templatetags目錄下,創(chuàng)建my_tags.py,這個文件名,是可以隨便的

先來增加一個乘法的標(biāo)簽

from django importtemplate

register=template.Library()

@register.simple_tagdefmul_tag(x,y):return x*y

View Code

修改article_detail.html,調(diào)用這個自定義標(biāo)簽

{% extends "base.html" %}

{% block content %}

{% load my_tags %}

{% mul_tag 2 7 %}

{{ article_obj.title }}

{{ article_obj.content }}{% endblock %}

View Code

必須重啟django項目,否則模板無法引用自定義標(biāo)簽!

必須重啟django項目,否則模板無法引用自定義標(biāo)簽!

必須重啟django項目,否則模板無法引用自定義標(biāo)簽!

隨便訪問一篇文章,出現(xiàn)一個14,說明調(diào)用成功了

那么這個my_tags,如何渲染左側(cè)的分類,標(biāo)簽,歸檔呢?

新建標(biāo)簽get_query_data,必須返回一個字典

將視圖函數(shù)中的相關(guān)代碼,復(fù)制過來即可。

from django importtemplate

register=template.Library()

@register.simple_tagdefmul_tag(x,y):return x*yfrom blog.models importCategory,Tag,Article,UserInfofrom django.db.models importCount,Avg,Max

@register.inclusion_tag("left_region.html")defget_query_data(username):

user= UserInfo.objects.filter(username=username).first()#查詢當(dāng)前站點對象

blog =user.blog#查詢當(dāng)前站點每一個分類的名稱以及對應(yīng)的文章數(shù)

cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#print(cate_list)

#查詢當(dāng)前站點每一個標(biāo)簽的名稱以及對應(yīng)的文章數(shù)

tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values_list("title", "c")#日期歸檔

date_list = Article.objects.filter(user=user).extra(select={"y_m_date": "strftime('%%Y/%%m',create_time)"}).values("y_m_date").annotate(c=Count("title")).values_list("y_m_date", "c")#print(date_list)

return {"blog":blog,"username":username,"cate_list":cate_list,"tag_list":tag_list,"date_list":date_list}

View Code

@register.inclusion_tag("left_region.html") 表示將返回結(jié)果渲染給left_region.html

如果在模板中有調(diào)用left_redig.html,那么這個文件,就會渲染,是渲染后的html文件!

在templates中新建文件left_region.html

隨筆分類

{% for cate in cate_list %}

{{ cate.0 }}({{ cate.1 }})

{% endfor %}

我的標(biāo)簽

{% for tag in tag_list %}

{{ tag.0 }}({{ tag.1 }})

{% endfor %}

日期歸檔

{% for date in date_list %}

{{ date.0 }}({{ date.1 }})

{% endfor %}

View Code

修改base.html,將

Title{#公共樣式#}

{#個人站點主題樣式#}

{#bootstrap#}

{{ blog.title }}

{#加載自定義標(biāo)簽?zāi)K#}

{% load my_tags %}

{#調(diào)用get_query_data標(biāo)簽,它返回left_region.html,是已經(jīng)被渲染過的文件#}

{% get_query_data username %}

{% block content %}

{% endblock %}

View Code

此時刷新網(wǎng)頁,效果同上!

修改views.py中的視圖函數(shù),刪除get_query_data!

刪除homesite和article_detail兩個視圖函數(shù)多余的代碼

from django.shortcuts importrender,HttpResponse,redirectfrom django.contrib importauthfrom blog.models importArticle,UserInfo,Blog,Category,Tagfrom django.db.models importSum,Avg,Max,Min,Count#Create your views here.

deflogin(request):if request.method=="POST":

user=request.POST.get("user")

pwd=request.POST.get("pwd")#用戶驗證成功,返回user對象,否則返回None

user=auth.authenticate(username=user,password=pwd)ifuser:#登錄,注冊session

#全局變量 request.user=當(dāng)前登陸對象(session中)

auth.login(request,user)return redirect("/index/")return render(request,"login.html")defindex(request):

article_list=Article.objects.all()return render(request,"index.html",{"article_list":article_list})def logout(request): #注銷

auth.logout(request)return redirect("/index/")def query_current_site(request,username): #查詢當(dāng)前站點的博客標(biāo)題

#查詢當(dāng)前站點的用戶對象

user = UserInfo.objects.filter(username=username).first()if notuser:return render(request, "not_found.html")#查詢當(dāng)前站點對象

blog =user.blogreturnblogdef homesite(request,username,**kwargs):"""查詢

:param request:

:param username:

:return:"""

print("kwargs", kwargs)

blog=query_current_site(request,username)#查詢當(dāng)前用戶發(fā)布的所有文章

if notkwargs:

article_list= Article.objects.filter(user__username=username)else:

condition= kwargs.get("condition")

params= kwargs.get("params")#判斷分類、隨筆、歸檔

if condition == "category":

article_list= Article.objects.filter(user__username=username).filter(category__title=params)elif condition == "tag":

article_list= Article.objects.filter(user__username=username).filter(tags__title=params)else:

year, month= params.split("/")

article_list= Article.objects.filter(user__username=username).filter(create_time__year=year,

create_time__month=month)return render(request,"homesite.html",{"blog":blog,"username":username,"article_list":article_list})defarticle_detail(request,username,article_id):

blog=query_current_site(request,username)#查詢指定id的文章

article_obj = Article.objects.filter(pk=article_id).first()return render(request,'article_detail.html',{"blog":blog,"username":username,'article_obj':article_obj})

View Code

注意:get_query_data標(biāo)簽只是定義了左側(cè)的標(biāo)簽!那么homesite和article_detail兩個視圖函數(shù),需要知道當(dāng)前站點的博客標(biāo)題。

所以需要專門定義個函數(shù),來獲取博客標(biāo)題!

修改article_detail.html,刪除測試的自定義標(biāo)簽

{% extends "base.html" %}

{% block content %}

{{ article_obj.title }}

{{ article_obj.content }}{% endblock %}

View Code

重新訪問個人站點,隨便亂點,效果同上!

Inclusion tags的優(yōu)點:

1.不用在視圖函數(shù)中return字典

2.數(shù)據(jù)和樣式結(jié)合在一起,返回一個渲染后的html

詳情頁顯示html代碼問題

訪問一篇博客詳情,比如:

http://127.0.0.1:8000/xiao/articles/5/

效果如下:

那么django響應(yīng)給瀏覽器的,真的是原來的html代碼嗎?

修改id為5的文章記錄,修改content字段的數(shù)據(jù),先備份一下,改成一個h1標(biāo)簽。

刷新網(wǎng)頁,效果如下:

打開瀏覽器控制臺-->network,查看這次請求的響應(yīng)體

發(fā)現(xiàn)代碼被轉(zhuǎn)義了!那么是誰轉(zhuǎn)義了呢?當(dāng)然是....

注意:這不是瀏覽器的鍋,是django轉(zhuǎn)義的,這是它的安全策略做的。遇到html或者js代碼,會自動轉(zhuǎn)義!

那么我們不要django轉(zhuǎn)義呢?使用safe過濾器即可!

修改article_detail.html中的代碼

{{ article_obj.content|safe }}

重新刷新頁面,效果如下:

注意:這樣有一個安全隱患!

舉例:將內(nèi)容修改為一段js代碼

重新刷新頁面,它會有一個提示框

注意:它只會彈一次。如果是下面這段代碼呢?

數(shù)據(jù)庫記錄如下:

刷新頁面試試?不用想了,你今天啥事不用干,瘋狂的點擊吧!

那么既要網(wǎng)頁安全,又需要網(wǎng)站展示真實的內(nèi)容,怎么辦呢?

答案就是:數(shù)據(jù)庫不存儲html代碼即可!存html和js代碼時,需要做特殊處理。

后面講到富文本編輯器,會講到。完美解決這個問題!

總結(jié)

以上是生活随笔為你收集整理的python个人网站开发_python 全栈开发,Day81(博客系统个人主页,文章详情页)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 成人做爰免费视频免费看 | 国产九九热 | 国产原创在线观看 | 丰满人妻一区二区三区免费 | 精品国产乱码久久久久久婷婷 | 99国产精品99| 激情五月激情综合网 | 亚洲最大的成人网 | 欧美黄色片 | 在线xxxx | 国模在线视频 | 精品视频在线观看一区 | 神马久久久久久久久久久 | a视频网站| 视频在线观看你懂的 | 香蕉视频网站在线 | 日本少妇性高潮 | 欧美日韩国产精品 | 伊人春色在线视频 | 欧美一级性生活 | 日韩精品一线二线三线 | av在线毛片| 亚洲国产999 | 嫩草一区 | 日本免费无人高清 | 蜜桃av噜噜一区二区三区小说 | 国产aaa大片| 大尺度做爰床戏呻吟舒畅 | 性激情视频 | 精品99在线观看 | 少妇一级淫片免费看 | 97人妻精品一区二区三区视频 | www.av视频在线观看 | 日批视频免费看 | 秋霞毛片少妇激情免费 | 希岛婚前侵犯中文字幕在线 | 窝窝午夜精品一区二区 | 国产网红在线 | 国产免费黄色av | 波多野结衣之双调教hd | 日韩欧美在线观看一区 | 91精产国品一二三 | 日本免费一二区 | 在线成人av网站 | 最新亚洲精品 | 亚洲一卡二卡在线 | 在线播放www | 亚洲精品热 | 波多野结衣国产 | 中文字幕第8页 | 国产一级做a | 国产女主播在线 | 人妻精油按摩bd高清中文字幕 | 91久久精品一区二区三区 | 高清乱码毛片入口 | 国产免费脚交足视频在线观看 | 性视屏| 亚洲AV无码一区二区伊人久久 | 韩毛片| 日韩日日夜夜 | 91麻豆成人精品国产免费网站 | 日本欧美一区二区 | 看91 | av日韩一区 | 清纯唯美亚洲综合 | 麻豆国产在线视频 | 内射国产内射夫妻免费频道 | 沟厕沟厕近拍高清视频 | 伊人久久五月 | 国产一区二区三区视频免费在线观看 | 精品女同一区 | 叼嘿视频91 | 一级片在线免费 | 亚洲在线观看视频 | 91黄色看片 | 国产一二区在线观看 | 亚洲一区电影网 | 免费在线欧美 | 91精品久久久久久综合五月天 | 99热久久这里只有精品 | 日本国产三级xxxxxx | 8ppav | 亚洲天堂网一区二区 | 国产精品电影 | 色偷偷噜噜噜亚洲男人的天堂 | 日本免费在线视频 | 日本免费网站 | 日韩 欧美 综合 | 国产综合av | 日韩中文字幕一区二区三区四区 | 日本一区免费视频 | 日韩一级黄色录像 | 舌奴调教日记 | 日韩国产综合 | 久久午夜电影网 | 国产精品扒开腿做爽爽爽a片唱戏 | 亚洲专区区免费 | 福利毛片 | 亚洲国产剧情在线观看 |