FBV视图


FBV视图

视图(view)是django MTV架构中的V部分,主要负责用户请求和生成相应的相应内容。我们用视图函数(定义def函数)处理处理HTTP请求,这种方式称为FBV。

设置响应方式

1. 返回响应内容:

视图函数通过return方式返回响应内容,然后生成相应的网页内容呈现在浏览器上。若要设置不同的响应方式,则应使用django内置的响应类,内置的部分响应类如下:

响应类型 说明
HttpResponse(‘hello‘) 状态码200,请求被服务器成功接收
HttpResponseRedirect(‘/‘) 状态码302,重定向至首页
HttpResponsePermanentRedirect('/') 状态码301,永久重定向至首页/td>
HttpResponseBadRequest('400') 状态码400,访问页面不存在或请求错误
HttpResponseNotFound('404') 状态码404,网页不存在或网页失效
HttpResponseForbidden('403') 状态码403,没有访问权限
HttpReseponseNotAllowed('405') 状态码405,不允许使用此请求方式
HttpReseponseServerError('500') 状态码500,服务器错误

不同的响应方式代表不同的HTTP状态码,作用是web服务器告诉浏览器当前网页的请求状态,例:

# urls.py文件
from django.urls import path, re_path
from . import views
urlpatterns = [
    path('', views.index),
]
#views.py
from django.shortcuts import render
from django.http import HttpResponse
import os
# Create your views here.
def index(request):
    return HttpResponse('hello world', status=200) # 返回200状态码,表示请求已被成功的接收并处理。

render函数:

从HttpResponse中可知,若要生成网页内容,就要将网页内容以字符串形式表示,这增加了代码量,同时也没有体现模板的作用,因此,django定义了render函数。

def render(request, template_name, context=None, content_type=None, status=None, using=None):
  • request:浏览器向服务器发送的请求对象,包含用户信息,请求方式等。
  • template_name:设置模板文件名,用于生成网页内容。
  • context:对模板变量进行赋值,以字典格式表示,默认为空字典。
  • content_type:响应内容的数据格式,一般使用默认值。
  • status:状态码,默认200.
  • using:设置模板引擎,解析模板文件。
# views.py
from django.shortcuts import render
from django.http import HttpResponse, Http404, StreamingHttpResponse, FileResponse
import os
# Create your views here.

def index(request):
    text = {'title': 'django'}
    # 传入模板文件index.html, 
    return render(request, 'index.html', text)
<!-- index.html文件 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h3>{{ title }}</h3>
</body>
</html>

视图函数中定义变量text作为render的参数context,模板index.html里通过模板变量{{title}}获取变量text的数据,模板变量的命名必须与字典中的key名称相同。若传递的变量过多,则可以使用python的内置语法locals()取代参数context。

2. 设置重定向:

  • 重定向的状态码为301与302,301重定向是永久重定向,302重定向是临时重定向,区别在于搜索引擎的抓取。
  • django中定义了HttpResponseRedirect与HttpResponsePermanentRedirect类,这两个类继承于HttpResponseRedirectBase类,HttpResponseRedirectBase类继承于HttpResponse类。
  • HttpResponseRedirect与HttpResponsePermanentRedirect类只需传入路由地址即可,但不支持路由命名传入。
  • 为解决路由命名传入,django定义了redirect函数(官方的注释已经很清楚了,不解释了):

    # 官方定义
    def redirect(to, *args, permanent=False, **kwargs):
        """
        Return an HttpResponseRedirect to the appropriate URL for the arguments
        passed.
    
        The arguments could be:
    
            * A model: the model's `get_absolute_url()` function will be called.
    
            * A view name, possibly with arguments: `urls.reverse()` will be used
              to reverse-resolve the name.
    
            * A URL, which will be used as-is for the redirect location.
    
        Issues a temporary redirect by default; pass permanent=True to issue a
        permanent redirect.
        """
        redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
        return redirect_class(resolve_url(to, *args, **kwargs))

3. 异常响应:

异常响应是指状态码为404与500的响应状态。同一个网站的异常响应的所返回的页面都是相同的,因此应当在django中配置全局异常响应。django全局异常响应应在项目名下的urls.py文件中配置。

# djangoProject/urls.py
from django.contrib import admin
from django.urls import path, re_path, include
from django.views.static import serve
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', include(('index.urls', 'index'), namespace='index')),
]
# 全局404页面配置
handler404 = 'index.views.page_not_found'
# 全局500页面配置
handler500 = 'index.views.page_error'
# index/urls.py
from django.shortcuts import render
# Create your views here.

def page_not_found(request, exception):
    return render(request, '404.html', status=404)


def page_error(request):
    return render(request, '500.html', status=500)

若要访问404和500页面则需要关闭django的Debug模式(DEBUG = False),并更改ALLOWED_HOSTS = [‘*’],否则你将看到django开发模式下的404页面或500页面。

4. 文件下载功能:

django提供三种方式实现文件下载功能,它们分别是HttpResponse,StreamingHttpResponse,FileResponse。

  • HttpResponse:所有响应过程的核心类,底层功能类是HttpResponseBase。

    class HttpResponse(HttpResponseBase):
        """
        An HTTP response class with a string as content.
    
        This content that can be read, appended to, or replaced.
        """
  • StreamingHttpResponse:在HttpResponse类的基础上继承和重写,适用于大规模的数据响应和文件传输响应。

    class StreamingHttpResponse(HttpResponseBase):
        """
        A streaming HTTP response class with an iterator as content.
    
        This should only be iterated once, when the response is streamed to the
        client. However, it can be appended to or replaced with a new iterator
        that wraps the original content (or yields entirely new content).
        """
  • 在StreamingHttpResponse类的基础上继承和重写,只适用于文件的传输响应。

    class FileResponse(StreamingHttpResponse):
    """
    A streaming HTTP response class optimized for files.
    """

HttpResponse,StreamingHttpResponse,FileResponse的差异:

  • HttpResponse的工作原理是将文件读取并全部载入内存;如果下载的文件过大,就会占用过多的内存。
  • StreamingHttpResponse,FileResponse都是将文件分批写入磁盘。
  • StreamingHttpResponse适用范围更广,FileResponse适用于文件输出。

使用方式:

  • # djangoProject/urls.py
    from django.contrib import admin
    from django.urls import path, re_path, include
    from django.conf import settings
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', include(('index.urls', 'index'), namespace='index')),
    ]
  • # index/urls.py
    from django.urls import path, re_path
    from . import views
    urlpatterns = [
        path('download/file1', views.download1, name='download1'),
        path('download/file2', views.download2, name='download2'),
        path('download/file3', views.download3, name='download3'),
    ]
  • # index/views.py
    from django.shortcuts import render
    from django.http import HttpResponse, Http404, StreamingHttpResponse, FileResponse
    import os
    # Create your views here.
    
    def download1(request):
        file_path = 'C:\\Users\\ren_r\\Desktop\\1.jpg'
        try:
            r = HttpResponse(open(file_path, 'rb'))
            r['content_type'] = 'application/octet-stream'
            r['Content-Disposition'] = 'attachment;filename=cat1.jpg'
            return r
        except Exception:
            raise Http404('Download error')
    
    def download2(request):
        file_path = 'C:\\Users\\ren_r\\Desktop\\2.jpg'
        try:
            r = StreamingHttpResponse(open(file_path, 'rb'))
            r['content_type'] = 'application/octet-stream'
            r['Content-Disposition'] = 'attachment;filename=cat2.jpg'
            return r
        except Exception:
            raise Http404('Download error')
    
    def download3(request):
        file_path = 'C:\\Users\\ren_r\\Desktop\\3.jpg'
        try:
            r = FileResponse(open(file_path, 'rb'), as_attachment=True, filename='nature.jpg')
            return r
        except Exception:
            raise Http404('Download error')
    
  • <!-- templates/index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
    </head>
    <body>
    <a href="{% url 'index:download1' %}">1.jpg</a>
    <br>
    <a href="{% url 'index:download2' %}">2.jpg</a>
    <br>
    <a href="{% url 'index:download3' %}">3.jpg</a>
    </body>
    </html>

HTTP请求对象:

1. HTTP请求对象:

  • Django在接收到http请求之后,会根据http请求携带的参数以及报文信息创建一个WSGIRequest对象,并且作为视图函数第一个参数传给视图函数。也就是我们经常看到的request参数。在这个对象上我们可以找到客户端上传上来的所有信息。这个对象的完整路径是django.core.handlers.wsgi.WSGIRequest。
  • WSGIRequest对象常用属性:

    • path:请求服务器的完整“路径”,但不包含域名和参数。
    • method:代表当前请求的http方法。比如是GET还是POST。
    • GET:一个django.http.request.QueryDict对象。操作起来类似于字典。这个属性中包含了所有以?xxx=xxx的方式上传上来的参数。
    • POST:也是一个django.http.request.QueryDict对象。这个属性中包含了所有以POST方式上传上来的参数。
    • FILES:也是一个django.http.request.QueryDict对象。这个属性中包含了所有上传的文件。
    • COOKIES:一个标准的Python字典,包含所有的cookie,键值对都是字符串类型。
    • session:一个类似于字典的对象。用来操作服务器的session。
    • META:存储的客户端发送上来的所有header信息。
  • WSGIRequest对象常用方法:

    • is_secure():是否是采用https协议。
    • is_ajax():是否采用ajax发送的请求。原理就是判断请求头中是否存在X-Requested-With:XMLHttpRequest。
    • get_host():服务器的域名。如果在访问的时候还有端口号,那么会加上端口号。比如www.baidu.com:9000。
    • get_full_path():返回完整的path。如果有查询字符串,还会加上查询字符串。比如/music/bands/?print=True。
    • get_raw_uri():获取请求的原始的完整的url。

2. 文件上传功能:

  • # djangoProject/urls.py
    from django.contrib import admin
    from django.urls import path, re_path, include
    from django.conf import settings
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', include(('index.urls', 'index'), namespace='index')),
    ]
  • # index/views.py
    from django.shortcuts import render
    from django.http import HttpResponse, Http404, StreamingHttpResponse, FileResponse
    import os
    # Create your views here.
    def upload(request):
        # 判断请求方法
        if request.method == 'POST':
            # myFile对象包含了文件的基本信息,如:myFILE.name,myFILE.size,myFILE.content_type等。
            myFile = request.FILES.get('myFile', None)
            if not myFile:
                return HttpResponse('upload failed')
            # 二进制写操作
            f = open(os.path.join("e://", myFile.name), 'wb+')
            # 分块写文件,若使用myFile.read(),则会读取全部上传的数据,适用于小文件上传。myFile.chunks()分块读,用for语句分块写入文件。myFile.multiple_chunks()判断文件大小,文件大小小于>2.5MB返回True,否则返回False。用此方法可判断算法使用read()方法或chunks()方法。
            for chunk in myFile.chunks():
                f.write(chunk)
            f.close()
            return HttpResponse('upload over')
        else:
            return render(request, 'index.html')
        
  • # index/urls.py
    from django.urls import path, re_path
    from . import views
    urlpatterns = [
        path('upload/', views.upload, name='upload'),
    ]    
  • <!-- templates/index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
    </head>
    <body>
    <!-- enctype="multipart/form-data"必填 --> 
    <form enctype="multipart/form-data" action="{% url 'index:upload' %}", method="post">
        <input type="file" name="myFile">
        <input type="submit" value="submit">
    </form>
    </body>
    </html>

声明:Hello World|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - FBV视图


我的朋友,理论是灰色的,而生活之树是常青的!