Diango博客--13.將“視圖函數”類轉化為“類視圖”

文章目錄

    • 0.思路引導
    • 1.ListView
    • 2.將 index 視圖函數改寫為類視圖
    • 3.將 category 視圖函數改寫為類視圖
    • 4.將 archive 視圖函數改寫成類視圖
    • 5.將 tag 視圖函數改寫成類視圖
    • 6.DetailView
    • 7.將DetailView視圖函數改寫成類視圖

0.思路引導

1)在開發網站的過程中,有一些視圖函數雖然處理的對象不同,但是其大致的代碼邏輯是一樣的。比如一個博客和一個論壇,通常其首頁都是展示一系列的文章列表或者帖子列表;

2)對處理首頁的視圖函數來說,其處理的邏輯即:首先從數據庫取出文章或者帖子列表,然后將這些數據傳遞給模板并渲染模板;

3)于是,django 把這些相同的邏輯代碼抽取了出來,寫成了一系列的通用視圖函數,即基于類的通用視圖(Generic Class Based View);

4)使用類視圖是 django 推薦的做法,熟悉了類視圖的使用方法后,能夠減少視圖函數的重復代碼,節省開發時間。

接下來就讓我們把博客應用中的視圖函數改成基于類的通用視圖。

1.ListView

在我們的博客應用中,有幾個視圖函數是從數據庫中獲取文章(Post)列表數據的:

文件位置:blog/views.py

def index(request):# ...def archive(request, year, month):# ...def category(request, pk):# ...def tag(request, pk):# ...

這些視圖函數都是從數據庫中獲取文章(Post)列表,唯一的區別就是獲取的文章列表可能不同。比如 index 獲取全部文章列表,category 獲取某個分類下的文章列表。

針對這種從數據庫中獲取某個模型列表數據(比如這里的 Post 列表)的視圖,Django 專門提供了一個 ListView 類視圖。

2.將 index 視圖函數改寫為類視圖

文件位置:blog/views.py

原視圖函數如下:


def index(request):post_list = Post.objects.all()return render(request, 'blog/index.html', context={'post_list': post_list})

修改成如下所示:

from django.views.generic import ListViewclass IndexView(ListView):model = Posttemplate_name = 'blog/index.html'context_object_name = 'post_list'

注意:

1)要寫一個類視圖,首先需要繼承 django 提供的某個類視圖。至于繼承哪個類視圖,需要根據你的視圖功能而定。比如這里 IndexView 的功能是從數據庫中獲取文章(Post)列表,ListView 就是從數據庫中獲取某個模型列表數據的,所以 IndexView 繼承 ListView。

2)model:將 model 指定為 Post,告訴 django 我要獲取的模型是 Post。

3)template_name:指定這個視圖即將去渲染的模板。

4)context_object_name:指定獲取的模型列表數據保存的變量名,這個變量會被傳遞給模板。

接下來,需要更改blog 的 URL 配置。

文件位置:blog/urls.py

原文件如下:

app_name = 'blog'
urlpatterns = [path('', views.index, name='index'),...
]

修改為如下所示:

app_name = 'blog'
urlpatterns = [path('', views.IndexView.as_view(), name='index'),...
]

注意:
1)URL中每一個path對應著一個視圖函數,這樣當用戶訪問這個 URL 時,Django 就知道調用哪個視圖函數去處理這個請求了。

2)在 Django 中 URL 模式的配置方式就是通過 url 函數將 URL 和視圖函數綁定。比如 path(’’, views.index, name=‘index’),它的第一個參數是 URL 模式,第二個參數是視圖函數 index。

3)對 url 函數來說,第二個參數傳入的值必須是一個函數。而 IndexView 是一個類,不能直接替代 index 函數。好在將類視圖轉換成函數視圖非常簡單,只需調用類視圖的 as_view() 方法即可。

3.將 category 視圖函數改寫為類視圖

文件位置:blog/views.py

原視圖函數如下:

def category(request, pk):"""定義 分類 視圖"""# 記得在開始部分導入 Category 類cate = get_object_or_404(Category, pk=pk)post_list = Post.objects.filter(category=cate)#.order_by('-created_time')return render(request, 'blog/index.html', context={'post_list': post_list})

初步改寫如下:

class CategoryView(ListView):model = Posttemplate_name = 'blog/index.html'context_object_name = 'post_list'def get_queryset(self):cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))return super(CategoryView, self).get_queryset().filter(category=cate)

注意:

1)和 IndexView 不同的地方是,我們覆寫了父類的 get_queryset 方法。該方法默認獲取指定模型的全部列表數據,為了獲取指定分類下的文章列表數據,我們覆寫該方法,通過filter改變它的默認行為。

2)在類視圖中,從 URL 捕獲的路徑參數值保存在實例的 kwargs 屬性(是一個字典)里,非路徑參數值保存在實例的 args 屬性(是一個列表)里。

3)所以我們使了 self.kwargs.get(‘pk’) 來獲取從 URL 捕獲的分類 id 值。然后調用父類的 get_queryset 方法獲得全部文章列表,緊接著就對返回的結果調用了 filter 方法來篩選該分類下的全部文章并返回。

4)此外我們可以看到 CategoryView 類中指定的屬性值和 IndexView 中是一模一樣的,所以如果為了進一步節省代碼,甚至可以直接繼承 IndexView。

優化后如下:

class CategoryView(IndexView):def get_queryset(self):cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))return super(CategoryView, self).get_queryset().filter(category=cate)

接下倆,在 URL 配置中把 category 視圖替換成類視圖 CategoryView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('categories/<int:pk>/', views.CategoryView.as_view(), name='category'),
]

4.將 archive 視圖函數改寫成類視圖

文件位置:blog/views.py

原視圖函數如下:

def archive(request, year, month):"""定義 歸檔 視圖"""post_list = Post.objects.filter(created_time__year=year,created_time__month=month)#.order_by('-created_time')return render(request, 'blog/index.html', context={'post_list': post_list})

改寫如下:

 class ArchiveView(IndexView):def get_queryset(self):year = self.kwargs.get('year')month = self.kwargs.get('month')return super().get_queryset().filter(created_time__year=year, created_time__month=month)

接下倆,在 URL 配置中把 archive 視圖替換成類視圖 ArchiveView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('archives/<int:year>/<int:month>/', views.ArchiveView.as_view(), name='archive'),
]

5.將 tag 視圖函數改寫成類視圖

文件位置:blog/views.py

原視圖函數如下:

def tag(request, pk):# 記得在開始部分導入 Tag 類t = get_object_or_404(Tag, pk=pk)post_list = Post.objects.filter(tags=t)#.order_by('-created_time')return render(request, 'blog/index.html', context={'post_list': post_list})

改寫如下:

 class TagView(IndexView):def get_queryset(self):t = get_object_or_404(Tag, pk=self.kwargs.get('pk'))return super().get_queryset().filter(tags=t)

接下倆,在 URL 配置中把 tag 視圖替換成類視圖 TagView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('tags/<int:pk>/', views.TagView.as_view(), name='tag'),
]

6.DetailView

除了從數據庫中獲取模型列表的數據外,從數據庫獲取模型的一條記錄數據也是常見的需求。

比如查看某篇文章的詳情,就是從數據庫中獲取這篇文章的記錄然后渲染模板。

對于這種類型的需求,django 提供了一個 DetailView 類視圖。

7.將DetailView視圖函數改寫成類視圖

接下倆,將 detail 視圖函數轉換為等價的類視圖 PostDetailView視圖

文件位置:blog/views.py

原視圖函數如下:

def detail(request, pk):"""定義文章詳情頁視圖"""post = get_object_or_404(Post, pk=pk)#閱讀量+1post.increase_views()md = markdown.Markdown(extensions=['markdown.extensions.extra','markdown.extensions.codehilite',# 'markdown.extensions.toc',# 記得在頂部引入 TocExtension 和 slugifyTocExtension(slugify=slugify),])post.body = md.convert(post.body)m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)post.toc = m.group(1) if m is not None else ''return render(request, 'blog/detail.html', context={'post': post})

改寫如下:

class PostDetailView(DetailView):model = Posttemplate_name = 'blog/detail.html'context_object_name = 'post'def get(self, request, *args, **kwargs):# 覆寫 get 方法的目的是因為每當文章被訪問一次,就得將文章閱讀量 +1# get 方法返回的是一個 HttpResponse 實例# 之所以需要先調用父類的 get 方法,是因為只有當 get 方法被調用后,# 才有 self.object 屬性,其值為 Post 模型實例,即被訪問的文章 postresponse = super().get(request, *args, **kwargs)# 將文章閱讀量 +1# 注意 self.object 的值就是被訪問的文章 postself.object.increase_views()# 視圖必須返回一個 HttpResponse 對象return responsedef get_object(self, queryset=None):# 覆寫 get_object 方法的目的是因為需要對 post 的 body 值進行渲染post = super().get_object(queryset=None)md = markdown.Markdown(extensions=['markdown.extensions.extra','markdown.extensions.codehilite',# 記得在頂部引入 TocExtension 和 slugifyTocExtension(slugify=slugify),])post.body = md.convert(post.body)m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)post.toc = m.group(1) if m is not None else ''return post

注意:

1)首先我們為 PostDetailView 類指定了一些屬性的值,這些屬性的含義和 ListView 中一樣。

2)緊接著我們覆寫了 get 方法。這對應著 detail 視圖函數中將 post 的閱讀量 +1 的那部分代碼。事實上,你可以簡單地把 get 方法的調用看成是 detail 視圖函數的調用。

3)接著我們又復寫了 get_object 方法。對應著 detail 視圖函數中根據文章的 id(也就是 pk)獲取文章,然后對文章的 post.body 進行 Markdown 解析。

4)get 方法看成是 detail 視圖函數,至于其它的像 get_object、get_context_data 都是輔助方法,這些方法最終在 get 方法中被調用,這里你沒有看到被調用的原因是它們隱含在了 super(PostDetailView, self).get(request, *args, **kwargs) 即父類 get 方法的調用中。最終傳遞給瀏覽器的 HTTP 響應就是 get 方法返回的 HttpResponse 對象。

接下倆,在 URL 配置中把 detail 視圖替換成類視圖 PostDetailView:

文件位置:blog/urls.py

app_name = 'blog'
urlpatterns = [...path('posts/<int:pk>', views.PostDetailView.as_view(), name = 'detail'),
]

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452411.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452411.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452411.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

es6之數據結構 set,WeakSet,mapWeakMap

{let list new Set();list.add(1);list.add(2);list.add(1);console.log(list); //Set(2) {1, 2} let arr[1,2,3,1,2] let list2new Set(arr); console.log(list2); //Set(3) {1, 2, 3} } Set ES6 提供了新的數據結構 Set。它類似于數組&#xff0c;但是成員的值都是唯一的&a…

關于C語言中繼承和多態的實現

以下的內容綜合了多篇文章&#xff0c;加上一點自己的理解而成。目的為了給自己閱讀他們文章后做一個筆記。在末尾給出了這些文章的地址。 多態的實現可以采用以下幾種方式&#xff1a; (1)使用 vod * (萬能指針)來實現“編譯時多態”。 (2)使用函數指針來實現“運行時…

邊界測試

邊界條件邊界測試是單元測試中最后的也可能是最重要的任務。 軟件常常在它的邊界上失效&#xff0c;例如&#xff0c;處理n元數組的第n個元素時&#xff0c;或做到i次循環中的第i次重復時&#xff0c;往往會發生錯誤。 使用剛好小于、剛好等于和剛好大于最大值或最小值的數據結…

阿里云上Kubernetes集群聯邦

摘要&#xff1a; kubernetes集群讓您能夠方便的部署管理運維容器化的應用。但是實際情況中經常遇到的一些問題&#xff0c;就是單個集群通常無法跨單個云廠商的多個Region&#xff0c;更不用說支持跨跨域不同的云廠商。這樣會給企業帶來一些擔憂&#xff0c;如何應對可用區級別…

缺氧游戲計算機,缺氧PC最低什么配置一覽 你覺得高嗎

缺氧PC最低什么配置一覽&#xff0c;你覺得高嗎。游戲對于電腦有不同程度的要求&#xff0c;缺氧這款游戲也有著自己的配置要求&#xff0c;看看下面的缺氧PC最低什么配置一覽&#xff0c;你的硬件夠得上嗎。缺氧最低配置&#xff1a;首先公布的是官 方配置需求&#xff0c;目前…

Diango博客--14.使用 Django 項目中的 ORM 編寫偽造測試數據腳本

文章目錄0.思路引導1.腳本目錄結構2.使用 Faker 快速生成測試數據3.批量生成測試數據4.執行腳本5.效果展示0.思路引導 1&#xff09;為了防止博客首頁展示的文章過多以及提升加載速度&#xff0c;可以對文章列表進行分頁展示。 2&#xff09;不過這需要比較多的文章才能達到分…

基于Sql Server 2008的分布式數據庫的實踐

配置Sql Server 2008&#xff08;Win7&#xff09; 1.打開SQL server2012&#xff0c;使用windows身份登錄 2.登錄后&#xff0c;右鍵選擇“屬性”。左側選擇“安全性”&#xff0c;選中右側的“SQL Server 和 Windows 身份驗證模式”以啟用混合登錄模式 3.選擇“連接”&#x…

橫向技術分析C#、C++和Java優劣

本文將從技術人員的角度橫向分析C#、C和Java優劣&#xff0c;其實選擇Java陣營還是.NET陣營&#xff0c;大家可以根據自己的實際需要來確定。 C#誕生之日起&#xff0c;關于C#與Java之間的論戰便此起彼伏&#xff0c;至今不輟。拋卻Microsoft與Sun之間的恩怨與口角&#xff0c;…

軟件測試中的存根程序

存根程序用來代替被測試的模塊所調用的模塊&#xff0c;因此存根程序也稱為“虛擬子程序”&#xff0c;它利用被它代替的模塊的接口&#xff0c;只做盡可能少的數據操作。

計算機網絡應用云計算,計算機網絡云計算的類型

原標題&#xff1a;計算機網絡云計算的類型隨著現代計算機網絡技術的不斷發展&#xff0c;越來越多的與計算機網絡有關的現代化技術得以出現&#xff0c;并且有著廣泛的應用&#xff0c;其中云計算技術就是比較常見的一種&#xff0c;在實際應用中發揮著較高的價值。在信息時代…

sublime_text快捷鍵

1、注釋&#xff1a;選中文本后&#xff0c;CTRL / 2、CTRL N,CTRLS&#xff0c;保存成.html文件后&#xff0c;只需要輸入感嘆號&#xff01;&#xff0c;然后tab鍵&#xff0c;即可打印出基本的html格式&#xff01;轉載于:https://www.cnblogs.com/JAVA-STUDYER/p/855040…

Diango博客--15.通過 Django Pagination 實現簡單分頁(一)

文章目錄0.思路引導1.Paginator 類的常用方法2.用 Paginator 給文章列表分頁3.在模板中設置分頁導航4.效果展示0.思路引導 1&#xff09;當博客上發布的文章越來越多時&#xff0c;通常需要進行分頁顯示&#xff0c;以免所有的文章都堆積在一個頁面&#xff0c;影響用戶體驗。…

SpringMVC 測試 mockMVC

SpringMVC測試框架 基于RESTful風格的SpringMVC的測試&#xff0c;我們可以測試完整的Spring MVC流程&#xff0c;即從URL請求到控制器處理&#xff0c;再到視圖渲染都可以測試。 一 MockMvcBuilder MockMvcBuilder是用來構造MockMvc的構造器&#xff0c;其主要有兩個實現&…

自頂向下和自底向上測試的優缺點

自頂向下測試方法的主要優點是不需要測試驅動程序&#xff0c;能夠在測試階段的早期實現并驗證系統的主要功能&#xff0c;而且能在早期發現上層模塊的接口錯誤。 自頂向下測試方法的主要缺點是需要存根程序&#xff0c;可能遇到與此相聯系的測試困難&#xff0c;低層關鍵模塊中…

C++ class中的靜態(static)成員

C class中的靜態(static)成員 &#xff08;1&#xff09; 靜態數據成員 ①一般地靜態數據成員在該類定義之外被初始化&#xff0c;如同一個成員函數被定義在類定義之外一樣。在這種定義中的靜態成員的名字必須被其類名限定修飾&#xff0c;例如下面是_interestRate的初始…

用計算機彈可惜不是你,可惜不是你 還是幸虧不是你

一、 你沒有再挽留 我也沒有再回頭 就這樣 無風無雨也無晴 無疾而終二、 是我孤陋寡聞不知你心有人三、 如果作業有葬禮,全體學生定當盛裝出席.四、 縱使我有千般好 你也看不到 因為你沒有一雙愛我的眼睛五、 原來暫時共你沒緣分 來年先會變得更合襯六、 真的別回頭 你有未來 你…

PHP 完整實戰23種設計模式

PHP實戰創建型模式 單例模式 工廠模式 抽象工廠模式 原型模式 建造者模式 PHP實戰結構型模式 橋接模式 享元模式 外觀模式 適配器模式 裝飾器模式 組合模式 代理模式 過濾器模式 PHP實戰行為型模式 模板模式 策略模式 狀態模式 觀察者模式 責任鏈模式 訪問者模…

Diango博客--16.穩定易用的 Django 分頁庫,完善分頁功能(二)

文章目錄0.思路引導1.分頁效果概述2.分頁思路3.Django 第三方拓展&#xff1a;django-pure-pagination4.自定義模板0.思路引導 1&#xff09;在前面我們通過 Django Pagination 實現簡單分頁 中&#xff0c;我們實現了一個簡單的分頁導航。但效果有點差強人意&#xff0c;我們…

回歸測試

在集成測試過程中&#xff0c;每當一個新模塊結合進來時&#xff0c;程序就發生了變化&#xff1a;建立了新的數據流路徑&#xff0c;可能出現了新的I/O操作&#xff0c;激活了新的控制邏輯。在集成測試的范疇中&#xff0c;回歸測試是指重新執行已經做過的測試的某個子集&…

不同的寫法 其中 1 2 (試了下 沒有效果 ,先記載這里把)

轉載于:https://www.cnblogs.com/kaibindirver/p/9145455.html