您的位置:首页 > 编程语言 > Go语言

Django2.0-views(7)-类视图,paginator,page

2018-11-12 00:27 597 查看
版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abc666666_6/article/details/83964920

类视图

在写视图的时候,

Django
除了使用函数作为视图,也可以使用类作为视图。使用类视图可以使用类的一些特性,比如继承等。

View

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/<book_id>/",views.BookDetailView.as_view(),name='detail')
]

如果向传递参数,可以如下操作

# urls.py
urlpatterns = [
path('index/<id>', 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
请求,都会走
dispatch(request,*args,**kwargs)
方法,所以如果实现这个方法,将能够对所有请求都处理到。

TemplateView

django.views.generic.TemplateView
,这个类视图是专门用来返回模版的。

  • 如果渲染的这个模版不需要传递任何的参数,那么建议在urls中使用TemplateView

    # urls.py
    from django.vies.generic import TemplateView
    
    urlpatterns = [
    path('', TemplateView.as_view(template_name='about.html'))
    ]

在这个类中,有两个属性是经常需要用到的

  • template_name
    ,这个属性是用来存储模版的路径,
    TemplateView
    会自动的渲染这个变量指向的模版。
  • get_context_data
    ,这个方法是用来返回上下文数据的,也就是在给模版传的参数的。
# 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

urls.py
中的映射代码如下:

from django.urls import path

from myapp.views import HomePageView

urlpatterns = [
path('', HomePageView.as_view()),
]

ListView

在网站开发中,经常会出现需要列出某个表中的一些数据作为列表展示出来。比如文章列表,图书列表等等。可以使用

ListView

# 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)  # 过滤

models.py

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)

views.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")

urls.py

urlpatterns = [
path('add/', views.add_article)
path('about/', views.ArticleListView.as_view())
]

article_list.html

<body>
<ul>
{% for article in articles %}
<li> {{ article.title }} </li>
{% endfor %}
</ul>

</body>

Paginator和Page类

Paginator
Page
类都是用来做分页的。他们在
Django
中的路径为
django.core.paginator.Paginator
django.core.paginator.Page

在上面的ListView的

def get_context_data)
中的
context = super(ArticleListView, self).get_context_data(* *kwargs)
,
print(context)
打印出来的键值对就有上述类

Paginator属性

  1. count
    :总共有多少条数据。

  2. num_pages
    :总共有多少页。

  3. page_range
    :页面的区间。比如有三页,那么返回
    range(1,4)

    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: {}\npaginator.num_pages: {}\npaginator.page_range: {}\n".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常用属性和方法

  1. has_next()
    :是否还有下一页。
  2. has_previous()
    :是否还有上一页。
  3. next_page_number()
    :下一页的页码。最后一页会抛出异常
    raise EmptyPage(_('That page contains no results'))
  4. previous_page_number()
    :上一页的页码。 第一页使用会抛出异常
    raise EmptyPage(_('That page number is less than 1'))
  5. number
    :当前页。
  6. start_index
    :当前这一页的第一条数据的索引值。
  7. end_index
    :当前这一页的最后一条数据的索引值。
  • 代码
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: {}\npaginator.num_pages: {}\npaginator.page_range: {}\n".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()

使用

URLl
访问附带了查询字符串
?page=2
因为默认第一页的话
page.previous_page_number()
会抛异常。

True # 是否有下一页
True # 是否有上一页
3 # 后一页页数
1 # 前一页页数
2 # 第几页
26 #第二页的第一个索引
50 #第二页的最后一个索引
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: