Erlo

Django笔记:视图

时间:2020-10-17   阅读:10次   来源:博客园
页面报错
点赞

众所周知,Django采用的是MTV框架模式,本文介绍的就是其中的V(View视图)。用户在访问某个url后,在返回响应之前,通常需要进行一些业务逻辑上的处理,然后再将处理后的数据返回给客户端,在Django中,View视图就是专门用来做这部分负责业务逻辑的功能的,同时,视图也是Model模型与Template模板之间的桥梁,因为通常是通过模型从数据库中获取数据,经过视图处理后再渲染到模板中。Django中视图主要是以视图函数和类视图的方式来处理数据并返回响应,本文也主要是介绍这两种方式。

一、视图函数

视图函数通常写在app的views.py文件中,定义视图函数时需要注意以下几点:

  1. 函数的第一个参数必须是request,这是一个WSGIRequest对象(参考本文后面关于此对象的介绍),Django会将用户请求的相关信息都封装在这个对象中,我们可以直接从这个对象中获取相关请求信息。
  2. 函数的返回值必须是HttpResponseBase对象或其子类对象,通常是HttpResponse对象,或通过renderredirect封装一个HTML文件后的对象,它们都是HttpResponseBase的子类对象。
  3. urlpatterns中配置url映射关系时,直接配置对应函数名即可。

1、创建一个普通的视图函数

视图函数的定义,除了第一个参数必须是request之外,如果url中定义了参数,那么在视图函数中按顺序定义同名的参数即可。
视图函数的返回值通常是一个HttpResponse对象(一个普通的响应对象),或者通过renderredirect方法返回一个HTML模板,当然,如果想要给HTML模板中传递上下文参数变量,可以使用render方法的context参数指定一个字典即可。

"""urls.py:配置url映射关系"""
from django.urls import path
from .views import book, book_list

# 直接使用视图函数名称来进行映射即可
urlpatterns = [
    path('book/<book_id>/', book),
    path('book/list/', book_list)
]
"""views.py:定义视图函数"""
from django.http import HttpResponse
from django.shortcuts import render


# 如访问“/book/”或“/book/3/”就会执行此视图函数的内容
def book(request, book_id=1):
    text = '您正在阅读的图书id是:{}'.format(book_id)
    # 返回一个普通的响应对象
    return HttpResponse(text)


def book_list(request):
    # 通过render函数返回一个HTML模板,render的第一个参数也必须是request
    return render(request, 'book_list.html')

2、WSGIRequest对象 - request参数

Django在接收到HTTP请求之后,会将HTTP请求携带的参数以及报文信息封装在一个WSGIRequest对象中,然后传递给视图函数,也就是视图函数的第一个参数request。对源码感兴趣的话,可以打印下这个对象,WSGIRequest对象继承自HttpRequest,源码位置在django.core.handlers.wsgi
常用的属性:

常用的方法:

3、HttpResponse对象

视图函数中如果不想直接返回一个HTML模板,而是返回一个普通的响应对象,或者想自己在响应对象中定义一些数据,就可以使用HttpResponse对象。
常用的属性:

常用的方法:

JsonResponse对象
这个对象在from django.http import JsonResponse中,用来返回json对象,默认只能传递一个字典对象,如果传递的是非字典对象,则需要指定一个参数safe=False

4、render/render_to_string/redirect

render:用来返回一个HTML模板,可以通过from django.shortcuts import render直接导入,第一个参数必须是request(即视图函数的第一个参数request),第二个参数是模板路径字符串。如果要给模板传递上下文变量参数,可以通过字典的方式传递给context参数。
render_to_string:是用来将一个HTML模板转换为字符串,在from django.template.loader import render_to_string中,因为返回值是字符串,所以是不能直接返回的,而是需要传入HttpResponse再返回,但是浏览器中呈现的依然是原先HTML模板中的内容。
redirect:是用于url的重定向,可以通过from django.shortcuts import redirect直接导入,redirect(to, *args, permanent=False, **kwargs)通常只需要传入对应的url即可,也就是只需要指定to参数,permanent表示是否需要永久性重定向,默认为False

from django.shortcuts import render
from django.http import HttpResponse
from django.template.loader import render_to_string


def index1(request):
    # 先将模板转为一个字符串,到浏览器后又会反转回来
    # html_str = render_to_string('index.html')
    # return HttpResponse(html_str)
    
    # 直接传入一个模板
    return render(request, 'index.html')

def index2(request):
    username = request.GET.get('username')
    if username:
        return HttpResponse('这是首页!')
    else:
        return redirect('/login/')

5、限制请求方式

想要给视图函数指定或限制请求方式,可以使用django.views.decorators.http中的装饰器来实现。
常用的装饰器:

# 指定此视图只能使用GET或POST请求
@require_http_methods(['GET', 'POST'])
def add_article(request):
    # 获取并判断此次请求对应的请求method
    if request.method == 'GET':
        return render(request, 'add_article.html')
    else:
        # 如果是POST请求,则添加一条数据到Article模型(表)中
        title = request.POST.get('title')
        content = request.POST.get('content')
        # create方法:添加一条数据并保存到数据库
        Article.objects.create(title=title, content=content)
        return HttpResponse('success!')

二、类视图

视图的逻辑处理除了可以定义在函数中,还可以定义在类中,即类视图,常用的类视图有三种:ViewTemplateViewListView

1、View类视图

View类视图是一个通用的类视图,定义的类需要继承自from django.views.generic import View,定义此类视图时需要注意以下几点:

from django.views.generic import View


class BookDetailView(View):
    # 如访问的url为:detail/<book_id>/
    def get(self, request, book_id):
        return HttpResponse('success!')
    
    def http_method_not_allowed(self, request, *args, **kwargs):
        return HttpResponse('不支持GET以外的请求方法!')

2、TemplateView类视图

如果一个url访问时并不需要专门的视图来进行处理,而是想直接返回一个固定写好的HTML文件,那么就可以使用TemplateView,也在from django.views.generic import TemplateView中,直接在配置url映射关系时使用它的as_view方法并指定template_name参数即可。

from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path('about/', TemplateView.as_view(template_name='about.html'))
]

虽然不用定义专门的视图来处理,但如果需要传递一些参数到模板中,那么就需要定义一个TemplateView的子类并重写get_context_data方法,示例如下:

from django.views.generic import TemplateView

class AboutView(TemplateView):
    # 指定HTML模板路径
    template_name = 'about.html'
    
    # 定义get_context_data方法,并返回一个字典,这个字典会用作模板的上下文对象
    def get_context_data(self, **kwargs):
        context = {'username': 'zhangsan'}
        return context
    

# url映射时就不需要再传递模板路径了
# urlpatterns = [
#     path('about/', AboutView.as_view())
# ]

3、ListView

如果页面中需要用到分页的功能,那么就可以考虑使用ListView视图了,它是专门用作分页功能的视图的,相比于普通的视图实现,它会非常的方便快捷,也是在from django.views.generic import ListView中,使用时需要定义一个它的子类并配置相关属性即可。
常用的属性和方法有:

示例:访问/article/list/时就会默认显示前paginate_by条数据,访问/article/list/?p=3时就显示第paginate_by乘以3组数据,url中的p是由page_kwargs指定的,也可以不改,就使用默认的page

"""views.py视图文件代码片段"""
from django.views.generic import ListView
from .models import Article


class ArticleListView(ListView):
    model = Article  # ORM模型类
    template_name = 'article_list.html'  # 响应的HTML模板
    context_object_name = 'articles'  # 模板中分页数据用到的上下文参数名称
    paginate_by = 10  # 每页显示的数据条数
    ordering = 'create_time'  # 指定排序字段
    page_kwargs = 'p'  # 访问指定页数时的查询字符串参数名称
"""urls.py映射文件代码片段"""
from django.urls import path
from .views import ArticleListView


urlpattern = [
    path('article/list/', ArticleListView.as_view())
]
<!-- article_list.html代码片段 -->
<ul>
    <!-- 此处的articles就是视图中context_object_name属性指定的值 -->
    {% for article in articles %}
    	<li>{{ article.title }}</li>
    {% endfor %}
</ul>

Paginator类和Page类
ListView视图中默认返回的上下文参数中有两个常用的对象paginatorpage_obj,对应于django.core.paginator.Paginator类和django.core.paginator.Page类,在HTML模板中会经常用到这两个对象的属性和方法。
Paginator常用属性和方法:

Page常用属性和方法:

4、在类视图中使用装饰器

在Django中如果想要给类方法添加装饰器,Django提供了一更加安全的使用方式,即使用from django.utls.decorators import method_decorator装饰器,使用时将自定义的装饰器函数传入,再去装饰对应的类或者方法即可。
访问url时,在进入对应类视图的方法之前,其实会先执行类视图的dispatch方法,所以如果想给类视图使用装饰器的话,可以直接装饰dispatch方法。装饰的方式也有两种,一种方式是直接在这个方法上使用对应的装饰器,另一种方式则在类定义上使用对应的装饰器,推荐使用后者,具体见示例代码。

from django.views.generic import View
from django.utls.decorators import method_decorator

# my_decorator为自定义的装饰器,将它放入method_decorator会更加安全
# 方式一:推荐采用这种直接装饰类的方式,传入自定义的装饰器和要装饰的方法即可
@method_decorator(my_decorator, name='dispatch')
class BookDetailView(View):
    def get(self, request, book_id):
        return HttpResponse('success!')
    
    # 方式二:通过重写dispatch的方式
    @method_decorator(my_decorator)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

注:本文为学习笔记,发现错误欢迎指出。

提交留言

评论留言

还没有评论留言,赶紧来抢楼吧~~

吐槽小黑屋()

* 这里是“吐槽小黑屋”,所有人可看,只保留当天信息。

  • Erlo吐槽

    Erlo.vip2020-10-21 23:25:54Hello、欢迎使用吐槽小黑屋,这就是个吐槽的地方。
  • 返回顶部