django 入門筆記:通用視圖類重構(gòu)視圖

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)建類視圖
  1. 創(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
    
  2. 綁定 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)該和之前的效果是一樣的


列表界面.png
詳情界面

有時(shí)候如果我們的數(shù)據(jù)過(guò)多,同一頁(yè)加載全部數(shù)據(jù)蛾号,用戶的體驗(yàn)肯定不好稠项,我們通過(guò)通用視圖類來(lái)創(chuàng)建分頁(yè),這邊為了方便顯示鲜结,我們會(huì)設(shè)置每頁(yè)加載一篇文章

通過(guò) ListView 創(chuàng)建分頁(yè)
  1. 指定 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
    
  2. 在模版中加入分頁(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è)
  1. 創(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())
    
  2. 通過(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>
    

最后做了分頁(yè)的效果界面
帶分頁(yè)列表

目前的分頁(yè)效果看上去并不那么美觀,在實(shí)際項(xiàng)目中精刷,我們優(yōu)化了分頁(yè)的顯示拗胜,具體的代碼就不貼了(我怕代碼太多你們會(huì)打我),可以下載項(xiàng)目查看怒允,這邊我們可以看下效果圖
優(yōu)化分頁(yè)列表

最后我們列下 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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末丽惶,一起剝皮案震驚了整個(gè)濱河市咖杂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚊夫,老刑警劉巖诉字,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異知纷,居然都是意外死亡壤圃,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門琅轧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伍绳,“玉大人,你說(shuō)我怎么就攤上這事乍桂〕迳保” “怎么了效床?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)权谁。 經(jīng)常有香客問(wèn)我剩檀,道長(zhǎng),這世上最難降的妖魔是什么旺芽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任沪猴,我火速辦了婚禮,結(jié)果婚禮上采章,老公的妹妹穿的比我還像新娘运嗜。我一直安慰自己,他們只是感情好悯舟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布担租。 她就那樣靜靜地躺著,像睡著了一般抵怎。 火紅的嫁衣襯著肌膚如雪奋救。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天便贵,我揣著相機(jī)與錄音,去河邊找鬼冗荸。 笑死承璃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蚌本。 我是一名探鬼主播盔粹,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼程癌!你這毒婦竟也來(lái)了舷嗡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嵌莉,失蹤者是張志新(化名)和其女友劉穎进萄,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體锐峭,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡中鼠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沿癞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片援雇。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖椎扬,靈堂內(nèi)的尸體忽然破棺而出惫搏,到底是詐尸還是另有隱情具温,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布筐赔,位于F島的核電站铣猩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏川陆。R本人自食惡果不足惜剂习,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望较沪。 院中可真熱鬧鳞绕,春花似錦、人聲如沸尸曼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)控轿。三九已至冤竹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茬射,已是汗流浹背鹦蠕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留在抛,地道東北人钟病。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像刚梭,于是被迫代替她去往敵國(guó)和親肠阱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容