django 及 rest_framework 筆記鏈接如下:
django 入門筆記:環(huán)境及項(xiàng)目搭建
django 入門筆記:數(shù)據(jù)模型
django 入門筆記:視圖及模版
django 入門筆記:Admin 管理系統(tǒng)及表單
django 入門筆記:通用視圖類重構(gòu)視圖
django_rest_framework 入門筆記:Serializer
django_rest_framework 入門筆記:視圖函數(shù)重構(gòu)
django_rest_framework 入門筆記:分頁(yè)霞溪,多條件篩選及權(quán)限認(rèn)證設(shè)置
django 自帶 user 字段擴(kuò)展及頭像上傳
終于到最后一部分了,這部分我們將通過(guò) django 自帶的通用視圖類替換之前寫的視圖函數(shù)棒妨,對(duì)視圖進(jìn)行重構(gòu)
利用 django 通用視圖類創(chuàng)建類視圖
-
創(chuàng)建視圖類
import markdown from django.shortcuts import render from django.views.generic import ListView, DetailView from django.shortcuts import get_object_or_404 from blog.models import Post # 獲取相應(yīng)模型下的全部數(shù)據(jù) def home(request): post_list = Post.objects.all() return render(request, 'blog/home.html', locals()) # 通過(guò) ListView 類來(lái)進(jìn)行修改 class HomeView(ListView): model = Post # 指定視圖模型 template_name = 'blog/home.html' # 指定渲染的模版 context_objects_name = 'post_list' # 對(duì)應(yīng)的模型列表數(shù)據(jù)保存的變量名 # ################################################################################# # 獲取特定條件下的模型數(shù)據(jù) def category(request, pk): category = get_object_or_404(Category, pk=pk) post_list = Post.objects.filter(category=category) return render(request, 'blog/home.html', locals()) # 通過(guò) ListView 類進(jìn)行修改 # 基本屬性同 HomeView 相同沿猜,也可以直接繼承 HomeView 然后復(fù)寫 get_queryset() 方法實(shí)現(xiàn) class CategoryView(ListView): model = Post template_name = 'blog/home.html' context_objects_name = 'post_list' # 該方法默認(rèn)返回指定模型的全部數(shù)據(jù)履羞,通過(guò)復(fù)寫該方法弧腥,改變默認(rèn)行為 def get_queryset(self): # 類視圖中庞溜,從 url 捕獲的命名組參數(shù)值保存在實(shí)例的 kwargs 中破讨,是一個(gè)字典 # 非命名組參數(shù)值保存在實(shí)例的 args 中孤页,是一個(gè)列表 category = get_object_or_404(Category, pk=kwargs.get('pk')) return super(CategoryView, self).get_queryset().filter(category=category) # ################################################################################# # 獲取具體的詳情 def post_detail(request, pk): post = get_object_or_404(Post, pk=pk) post.increase_views() post.body = markdown.markdown(post.body, extensions=[ 'markdown.extensions.extra', 'markdown.extensions.codehilite', ]) form = CommentForm() return render(request, 'blog/detail.html', locals()) class PostDetailView(DetailView): model = Post template_name = 'blog/detail.html' context_objects_name = 'post' # 方法返回一個(gè) HttpResponse 實(shí)例 def get(self, request, *args, **kwargs): # get 方法會(huì)通過(guò)調(diào)用 get_object 和 get_context——data 方法對(duì)模版渲染 # def get(self, request, *args, **kwargs): # self.object = self.get_object() # context = self.get_context_data(object=self.object) # return self.render_to_response(context) response = super(PostDetailView, self).get(request, *args, **kwargs) # 只有當(dāng) get 方法被調(diào)用后才有 self.object 屬性尔苦,即 post 實(shí)例 # 對(duì)應(yīng) post_detail 函數(shù)中的 post.increase_views() self.object.increase_views() return response # 根據(jù) post 的 pk 值獲取相應(yīng)的 post 實(shí)例 def get_object(self, queryset=None): post = super(PostDetailView, self).get_object(queryset=None) post.body = markdown.markdown(post.body, extensions=[ 'markdown.extensions.extra', 'markdown.extensions.codehilite', ]) return post # 返回一個(gè)字典,為模版變量字典行施,傳遞給相應(yīng)的模版 def get_context(self, **kwargs): context = super(PostDetailView, self).get_context(**kwargs) form = CommentForm() # 更新 context 的內(nèi)容允坚,必須調(diào)用 context.update(locals()) return context
-
綁定 url
urlpatterns = [ # url(r'^home/$', views.home, name='home'), url(r'^home/$', views.HomeView.as_view(), name='home'), # url(r'cate/(?P<pk>[0-9]+)/$', views.category, name='cate'), url(r'cate/(?P<pk>[0-9]+)/$', views.CategoryView.as_view(), name='cate'), # url(r'post/(?P<pk>[0-9]+)/$', views.post_detail, name='post'), url(r'post/(?P<pk>[0-9]+)/$', views.PostDetailView.as_view(), name='post'), ]
修改完后的界面應(yīng)該和之前的效果是一樣的
有時(shí)候如果我們的數(shù)據(jù)過(guò)多,同一頁(yè)加載全部數(shù)據(jù)蛾号,用戶的體驗(yàn)肯定不好稠项,我們通過(guò)通用視圖類來(lái)創(chuàng)建分頁(yè),這邊為了方便顯示鲜结,我們會(huì)設(shè)置每頁(yè)加載一篇文章
通過(guò) ListView 創(chuàng)建分頁(yè)
-
指定 ListView 中的 paginate_by 屬性來(lái)設(shè)置分頁(yè)
class PostListView(ListView): model = Post template_name = 'blog/home.html' context_objects_name = 'post_list' # 指定分頁(yè)展运,每頁(yè)數(shù)量為 1 paginate_by = 1
-
在模版中加入分頁(yè)
{# ...... #} {% if is_paginated %} <div class="pagination-simple"> {% if page_obj.has_previous %} <a href="?page={{ page_obj.previous_page_number }}">Previous</a> {% endif %} <span class="current"> Page {{ post_list.number }} of {{ post_list.paginator.num_pages }} </span> {% if page_obj.has_next %} <a href="?page={{ page_obj.next_page_number }}">Next</a> {% endif %} </div> {# ...... #}
通過(guò) Paginator 創(chuàng)建分頁(yè)
-
創(chuàng)建相應(yīng)的視圖
def home(request): limit = 10 posts = Post.object.all() paginator = Paginator(posts, limit) # 根據(jù)表單獲取頁(yè)碼 page = request.GET.get('page') try: post_list = paginator.page(page) # 獲取 num 頁(yè)碼下的列表 except PageNotAnInteger: post_list = paginator.page(1) # 如果 page 不是整數(shù)則返回第一頁(yè)列表 except EmptyPage: post_list = paginator.page(paginator.num_pages) # 如果沒(méi)有數(shù)據(jù)則返回最后一頁(yè)列表 return render(request, 'blog/home.html', locals())
-
通過(guò)模版進(jìn)行渲染
{% for post in post_list %} {{ post.title }}<br /> ... {% endfor %} <div class="pagination"> <span class="step-links"> {% if post_list.has_previous %} <a href="?page={{ post_list.previous_page_number }}">previous</a> {% endif %} <span class="current"> Page {{ post_list.number }} of {{ post_list.paginator.num_pages }} </span> {% if post_list.has_next %} <a href="?page={{ post_list.next_page_number }}">next</a> {% endif %} </span> </div>
最后我們列下 Paginator 常用屬性結(jié)束 django 的入門教程埂软,接下來(lái)會(huì)有 DRF 的入門教程,django 算是其基礎(chǔ)吧纫事,DRF 實(shí)現(xiàn)了前后端分離勘畔,剛好適合我這種 Android 開(kāi)發(fā)需要接口的。
from django.core.paginator import Paginator
item_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']
# 指定 paginator 的列表以及每頁(yè)顯示的列表數(shù)量
p = Paginator(item_list, 2)
print(p.count) # 返回列表的總數(shù) 14
print(p.num_pages) # 返回總頁(yè)數(shù) 7
print(p.page_range) # 返回頁(yè)數(shù)的范圍 (1, 8)
print(p.per_page) # 返回每頁(yè)列表的數(shù)量
print(p.object_list) # 返回所有的列表 item
# 通過(guò) page(num) 方法獲取 num 頁(yè)的列表 <Page 2 of 7>
page2 = p.page(2)
print(page2.number) # 獲取當(dāng)前頁(yè)的頁(yè)碼
print(page2.object_list) # 獲取該頁(yè)碼下的所有列表 ['c', 'd']
print(page2.has_next()) # 是否有下頁(yè) True
print(page2.has_previous()) # 是否有上頁(yè) True
print(page2.has_other_pages()) # 是否有其他頁(yè) True
# 如果沒(méi)有上/下一頁(yè)則返回 EmptyPage 錯(cuò)誤 EmptyPage: That page contains no results
print(page2.next_page_number()) # 獲取下一頁(yè)的頁(yè)碼 3
print(page2.previous_page_number()) # 獲取上一頁(yè)的頁(yè)碼 1
print(page2.start_index()) # 當(dāng)前頁(yè)第一個(gè) item 在列表中的位置 3
print(page2.end_index()) # 當(dāng)前頁(yè)最后一個(gè) item 在列表中的位置 4