Django 2.0-view(7)-クラスビュー、paginator、page

26663 ワード

クラスビュー
ビューを書くとき、Djangoは、関数をビューとして使用する以外に、クラスをビューとして使用することができる.クラスビューを使用すると、クラスのいくつかの特性、例えば継承などが使用されます.
ビューdjango.views.generic.Viewは、主なクラス図である.
すべてのクラスビューは彼に引き継がれます.自分のクラス図を書けば、彼にも引き継がれます.
その後、異なる方法が、現在要求されているmethodに従って実装される.
例えば、このビューは、getの方法でのみ要求されることができるので、このクラスにget(self,request,*args,**kwargs)の方法を定義することができる.このように類推すると、post方法を実装するだけであれば、クラス内でpost(self,request,*args,**kwargs)を実装する必要があるだけである.
from django.views import View
class BookDetailView(View):
    def get(self,request,*args,**kwargs):
        return render(request,'detail.html')
クラスビューが完了したら、urls.pyにマッピングされるべきであり、マッピングするときはViewのクラスの方法as_view()を呼び出して変換する必要がある.
urlpatterns = [        
    path("detail//",views.BookDetailView.as_view(),name='detail')
]
パラメータを渡すと、次のように操作できます.
# urls.py
urlpatterns = [
    path('index/', views.Index.as_views(), name = 'index')
]

# views.py
class Index(View):
    def get(self, id, *args, **kwargs):
        pass
get方法に加えて、Viewは、以下の方法['get','post','put','patch','delete','head','options','trace']をサポートする.Viewにユーザがアクセスした場合、定義されていない方法.例えば、クラスビューはget方法だけをサポートし、post方法が現れたら、405エラーが発生します.この要求はhttp_method_not_allowed(request,*args,**kwargs)に転送されます.サンプルコードは以下の通りです.
class Index(View):
    def post(self,request,*args,**kwargs):
        return HttpResponse("post!")

    def http_method_not_allowed(self, request, *args, **kwargs):
        return HttpResponse("     method :{}".format(request.method))
urls.pyにおけるマッピングは以下の通りである.
path("idnex/",views.Index.as_view(),name='add_book')
ブラウザでindex/にアクセスすると、get方式が採用されているため、index/post方法しかサポートされていません.
実際には method :GETの要求であれ、getの要求であれ、postの方法が実行されるので、この方法を実現すれば、すべての要求を処理することができる.
TemplateViewdispatch(request,*args,**kwargs)、このようなビューは、特別にモダリティを返すために使用される.
  • レンダリングされたこのモデルが任意のパラメータを伝達する必要がない場合、TemplateView
    # urls.py
    from django.vies.generic import TemplateView
    
    urlpatterns = [
        path('', TemplateView.as_view(template_name='about.html'))
    ]
    
  • をurlsで使用することを推奨する.
    このクラスでは、二つの属性がよく使われます.
  • django.views.generic.TemplateView、この属性はモダリティを格納するための経路であり、template_nameはこの変数指向のモダリティを自動的にレンダリングする.
  • TemplateViewは、この方法は、コンテキストデータを返すためのものであり、すなわち、テンプレートに送信されるパラメータである.
  • # myapp.views.py
    from django.views.generic import TemplateView
    
    class HomePageView(TemplateView):
        template_name = "home.html"
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context["name"] = "jack"
            return context
    
    get_context_dataにおけるマッピングコードは以下の通りである.
    from django.urls import path
    
    from myapp.views import HomePageView
    
    urlpatterns = [
        path('', HomePageView.as_view()),
    ]
    
    ListView
    ウェブサイトの開発では、リストとして表示されるデータの一部をリストに表示する必要があります.文章のリストや図書のリストなどです.urls.pyが使用できます.
    # views.py,             app     
    from django.views.generic import ListView
    
    class ArticleListView(ListView):
        model = Article  #     
        template_name = 'article_list.html'  #       
        paginate_by = 10  #            
        context_object_name = 'articles'  #                     
        ordering = 'create_time'  #            
        page_kwarg = 'page'  #              (?page=xxx)。   `page`。
    
        def get_context_data(self, **kwargs):  #         。
            context = super(ArticleListView, self).get_context_data(**kwargs)
            print(context)
            return context
    
        def get_queryset(self):  #           ,            ,           。               
            #    return Article.objects.all()
            return Article.objects.filter(id__lte=89)  #   
    
    ListView
    from django.db import models
    class Article(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        create_time = models.DateTimeField(auto_now_add=True)
    
    models.py
    from django.shortcuts import render
    from django.http import HttpResponse
    from .models import Article
    
    def add_article(request):
        articles = []
        for x in range(0,102):
            article = Article(title='  : %s'%x, content='  : %s'%x)
            articles.append(article)
    	Article.objects.bulk_create(articles)
        return HttpResponse("yes")
    
    views.py
    urlpatterns = [
        path('add/', views.add_article)
        path('about/', views.ArticleListView.as_view())
    ]
    
    urls.py
    <body>
        <ul>
            {% for article in articles %}
            	<li> {{ article.title }} li>
            {% endfor %}
        ul>
        
    body>
    
    PaginatorとPage類article_list.htmlおよびPaginatorクラスは、それぞれのページを作成するために使用されます.彼らのPageにおける経路はDjangoおよびdjango.core.paginator.Paginatorである.
    上のListViewのdjango.core.paginator.Pagedef get_context_data)に、context = super(ArticleListView, self).get_context_data(* *kwargs)の印刷されたキーのペアには上記の種類があります.
    Paginatorのプロパティ
  • print(context):全部でいくつのデータがありますか?
  • count:全部で何ページありますか?
  • num_pages:ページの間隔.例えば3ページがあれば、page_rangeに戻ります.
    class ArticleListView(ListView):
        model = Article
        template_name = "article.html"
        paginate_by = 25
        context_object_name = "articles"
        ordering = "create_time"
        page_kwarg = "page"
    
        def get_context_data(self, *, object_list=None, **kwargs):
            context = super(ArticleListView, self).get_context_data(**kwargs)
            paginator = context.get("paginator")  #   paginator
            print("paginator.count: {}
    paginator.num_pages: {}
    paginator.page_range: {}
    "
    .format(paginator.count, paginator.num_pages, paginator.page_range)) return context def get_queryset(self): return Article.objects.all()
    出力
    paginator.count: 103
    paginator.num_pages: 5
    paginator.page_range: range(1, 6)
    
  • Pageの一般的な属性と方法
  • range(1,4):次のページがあるかどうか.
  • has_next():前のページがあるかどうか.
  • has_previous():次のページのページ番号.最後のページに異常が投げられます.
  • next_page_number():前ページのページ番号.第一ページの使用は異常を投げます.
  • raise EmptyPage(_('That page contains no results')):現在のページ.
  • previous_page_number():現在のこのページの第1のデータのインデックス値.
  • raise EmptyPage(_('That page number is less than 1')):現在のこのページの最後のデータのインデックス値.
  • コード
  • class ArticleListView(ListView):
        model = Article
        template_name = "article.html"
        paginate_by = 25
        context_object_name = "articles"
        ordering = "create_time"
        page_kwarg = "page"
    
        def get_context_data(self, *, object_list=None, **kwargs):
            context = super(ArticleListView, self).get_context_data(**kwargs)
            # paginator = context.get("paginator")
            # print("paginator.count: {}
    paginator.num_pages: {}
    paginator.page_range: {}
    ".format(paginator.count, paginator.num_pages, paginator.page_range))
    # print(context) page = context.get("page_obj") # page_obj print(page.has_next()) print(page.has_previous()) print(page.next_page_number()) print(page.previous_page_number()) print(page.number) print(page.start_index()) print(page.end_index()) return context def get_queryset(self): return Article.objects.all()
    numberを使用して、照会文字列start_indexが添付されています.デフォルトの最初のページの場合はend_indexに異常があります.
    True #       
    True #       
    3 #      
    1 #      
    2 #    
    26 #         
    50 #