众所周知 ,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。
常用的属性:

  • path:请求服务器的完整路径,但不包含域名和参数 。如http://127.0.0.1:8000/login/ ,path的值就是/login/ 。
  • method:当前请求的HTTP方法,如GET、POST等。
  • GET:一个django.http.request.QueryDict对象,操作方式类似字典 ,存储了url中所有以?xxx=xxx格式上传的参数。
  • POST:一个django.http.request.QueryDict对象,操作方式类似字典,存储了url中所有以POST方式上传的参数 。
  • FILES:一个django.http.request.QueryDict对象 ,操作方式类似字典 ,存储了所有上传的文件信息。
  • COOKIES:一个标准的Python字典,包含所有的cookie,键值对都是字符串类型。
  • session:一个类似字典的对象 ,用来操作服务器的session 。
  • META:一个标准的Python字典,存储了客户端发送上来的所有header信息,字典中常用的项有:
    • CONTENT_LENGTH:请求的正文的长度(字符串类型)。
    • CONTENT_TYPE:请求的正文的MIME类型。
    • HTTP_ACCEPT:响应可接收的Content-Type 。
    • HTTP_ACCEPT_ENCODING:响应可接收的编码。
    • HTTP_ACCEPT_LANGUAGE:响应可接收的语言。
    • HTTP_POST:客户端发送的HOST值 。
    • HTTP_REFERER:访问当前页面之前的上一个访问页面的url。
    • QUERY_STRING:单个字符串形式的查询字符串(未解析过的形式)。
    • REMOTE_ADDR:客户端的IP地址 。如果服务器使用了ngix做反向代理或者负载均衡 ,那么这个值返回的就是127.0.0.1,此时可以使用HTTP_X_FORWARDED_FOR来获取,如:
    addr = request.META.get('HTTP_X_FORWARDED_FOR') if not addr: addr = request.META.get('REMOTE_ADDR')
    • REMOTE_HOST:客户端的主机名 。
    • REQUEST_METHOD:请求方法。
    • SERVER_NAME:服务器域名。
    • SERVER_PORT:服务器端口号(字符串类型) 。

常用的方法:

  • is_secure:是否是采用的https协议。
  • is_ajax:是否是采用ajax发送的请求。原理是判断请求头中是否存在X-Requested-With:XMLHttpRequest 。
  • get_host:服务器的域名 ,如果访问时有加上端口号,则会返回域名和端口号。
  • get_full_path:返回完整路径,包含查询字符串 ,但不包含域名。
  • get_raw_uri:获取请求的完整url 。

3 、HttpResponse对象

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

  • content:返回的内容。
  • status_code:返回的HTTP响应状态码 。
  • content_type:返回的数据的MIME类型 ,默认为text/html。浏览器会根据这个属性来决定怎么显示数据,如text/html则会解析这个字符串,text/plain则会显示为一个纯文本。常用的Content-Type有:
    • text/html:默认的类型 ,HTML文件 。
    • text/plain:纯文本 。如果出现中文乱码,可以在后面指定编码方式,如text/plain;charset=utf-8。
    • text/css:css文件。
    • text/javascript:js文件 。
    • multipart/form-data:文件提交。
    • application/json:json传输。
    • application/xml:xml文件 。
  • 设置请求头:可以使用字典的方式 ,如HttpResponse()['X-Access-Token']='xxx'。

常用的方法:

  • set_cookie:设置cookie信息。
  • delete_cookie:删除cookie信息 。
  • writeHttpResponse可以当作一个类似文件的对象,用此方法来写入数据到数据体content中。

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中的装饰器来实现 。
常用的装饰器:

  • require_http_methods:此装饰器可以传入一个请求method的列表 ,表示此视图或url只能使用指定的请求method来访问。
  • require_GET:指定此视图或url只能使用GET请求,相当于@require_http_methods(['GET'])。
  • require_POST:指定此视图或url只能使用POST请求,相当于@require_http_methods(['POST']) 。
  • require_safe:指定此视图或url只能使用GETHEAD请求 ,相当于@require_http_methods(['POST', 'HEAD'])。
# 指定此视图只能使用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!')

二 、类视图

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

1、View类视图

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

  • 如果想要指定允许的某种或多种请求方式 ,如GET等,则定义对应名称的方法即可,没有定义的方法则表示不允许这种请求方式 ,如def get(self, request):...,定义方式和视图函数是一样的,比如有一个固定的request参数 ,返回值必须是HttpResponseBase对象或其子类对象 。
  • 在配置url映射时需要使用类的as_view()方法,如path('detail/<book_id>/', BookDetailView.as_view()),当然 ,如果url中有指定参数 ,直接在类视图中的对应方法中按顺序添加同名的参数即可,也是和视图函数的定义一样的。
  • 如果用户访问了不支持的或没有定义的请求方法,那么默认会先去查找并执行类中的http_method_not_allowed(self, request, *args, **kwargs)方法 ,如果此方法没有定义,则返回一个405的错误。
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中 ,使用时需要定义一个它的子类并配置相关属性即可。
常用的属性和方法有:

  • model:页面中分页数据需要用到的ORM模型类。
  • template_name:指定返回的HTML模板 。
  • paginate_by:指定这个页面中展示的数据条数。
  • context_object_name:指定这个模板中分页数据需要用到的上下文参数名称。
  • ordering:指定数据的排列方式 。
  • page_kwarg:访问分页中第几页时用到的查询字符串参数,默认为page 。
  • get_context_data():获取上下文中的数据,如果需要额外添加数据到上下文中 ,可以重写这个方法。因为ListView中此方法本身就实现了许多功能,所以定义此视图时通常需要先使用super获取父类的结果,再在此结果中添加自己额外的上下文数据。
  • get_queryset():指定分页界面中展示所需的数据 ,默认为ORM模型类对应的全部数据,相当于xxx.objects.all(),如果不想返回所有数据 ,也可以使用filter等方法返回一个QuerySet对象,如xxx.objects.filter(id__lte=50)只返回id大于等于50的数据 。

示例:访问/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 urlpatterns = [ 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常用属性和方法:

  • count:总的数据条数 。
  • num_pages:总共有多少页。
  • page_range:比如总共有10页,那么返回的就是range(1, 11)。

Page常用属性和方法:

  • has_next:是否还有下一页 。
  • has_previous:是否还有上一页。
  • next_page_number:下一页的页码。
  • previous_page_number:上一页的页码 。
  • number:当前页的页码。
  • start_index:当前页的第一条数据的索引值。
  • end_index:当前页的最后一条数据的索引值 。

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)

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

文章来源于网络,如有侵权请联系站长QQ61910465删除
本文版权归qu快排seo www.sEoguRuBlog.com 所有,如有转发请注明来出,竞价开户托管,seo优化请联系QQ√61910465