第四章 Django框架——视图层views

第四章 Django框架——视图层views

一、视图函数

二、HttpRequest请求对象

三、HTTPResponse响应对象

四、CBV和FBV

五、JsonResponse

六、简单的文件上传方法

一、视图函数

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

from django.shortcuts import render, HttpResponse, HttpResponseRedirect, redirect
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

让我们逐行阅读上面的代码:

  • 首先,我们从 django.shortcuts模块导入了HttpResponse类,以及Python的datetime库。

  • 接着,我们定义了current_datetime函数。它就是视图函数。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request

    注意,视图函数的名称并不重要;不需要用一个统一的命名方式来命名,以便让Django识别它。我们将其命名为current_datetime,是因为这个名称能够精确地反映出它的功能。

  • 这个视图会返回一个HttpResponse对象,其中包含生成的响应。每个视图函数都负责返回一个HttpResponse对象。

 视图层,熟练掌握两个对象即可:请求对象(request)和响应对象(HttpResponse)

二、HttpRequest请求对象

 HttpRequest请求对象下的属性(除了特殊说明的之外,其他均为只读的):

 form表单不写method的情况下,默认为GET请求,切记改为POST请求

 何时使用POST请求与GET请求:
 ①POST:向服务器提交数据

 ②GET:请求数据,请求页面

请求相关的常用值:

  • path_info     返回用户访问url,不包括域名
  • method        请求中使用的HTTP方法的字符串表示,全大写表示。
  • GET              包含所有HTTP  GET参数的类字典对象
  • POST           包含所有HTTP POST参数的类字典对象
  • body            请求体,byte类型 request.POST的数据就是从body里面提取到的

 

HttpRequest请求对象下的常用方法:

1.HttpRequest.get_host()

  根据从HTTP_X_FORWARDED_HOST(如果打开 USE_X_FORWARDED_HOST,默认为False)和 HTTP_HOST 头部信息返回请求的原始主机。
   如果这两个头部没有提供相应的值,则使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有详细描述。

  USE_X_FORWARDED_HOST:一个布尔值,用于指定是否优先使用 X-Forwarded-Host 首部,仅在代理设置了该首部的情况下,才可以被使用。

  例如:"127.0.0.1:8000"

  注意:当主机位于多个代理后面时,get_host() 方法将会失败。除非使用中间件重写代理的首部。

 

2.HttpRequest.get_full_path()

  返回 path,如果可以将加上查询字符串。

  例如:"/music/bands/the_beatles/?print=true"

 

3.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

  返回签名过的Cookie 对应的值,如果签名不再合法则返回django.core.signing.BadSignature。

  如果提供 default 参数,将不会引发异常并返回 default 的值。

  可选参数salt 可以用来对安全密钥强力攻击提供额外的保护。max_age 参数用于检查Cookie 对应的时间戳以确保Cookie 的时间不会超过max_age 秒。

        复制代码
        >>> request.get_signed_cookie('name')
        'Tony'
        >>> request.get_signed_cookie('name', salt='name-salt')
        'Tony' # 假设在设置cookie的时候使用的是相同的salt
        >>> request.get_signed_cookie('non-existing-cookie')
        ...
        KeyError: 'non-existing-cookie'    # 没有相应的键时触发异常
        >>> request.get_signed_cookie('non-existing-cookie', False)
        False
        >>> request.get_signed_cookie('cookie-that-was-tampered-with')
        ...
        BadSignature: ...    
        >>> request.get_signed_cookie('name', max_age=60)
        ...
        SignatureExpired: Signature age 1677.3839159 > 60 seconds
        >>> request.get_signed_cookie('name', False, max_age=60)
        False
        复制代码
         


4.HttpRequest.is_secure()

  如果请求时是安全的,则返回True;即请求通是过 HTTPS 发起的。

 

5.HttpRequest.is_ajax()

  如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。

  大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。

  如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware, 
   你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。

请求相关方法
方法

注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:

request.POST.getlist("hobby")

三、HTTPResponse响应对象

 1.HTTPResponse()

 HttpResponse()括号内直接跟一个具体的字符串作为响应体。

 属性:

  • HttpResponse.content:响应内容
  • HttpResponse.charset:响应内容的编码
  • HttpResponse.status_code:响应的状态码

 2.render()

 结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象,简而言之就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。

  语法:render(request, template_name[, context])

  参数:

  • request: 用于生成响应的请求对象。
  • template_name:要使用的模板的完整名称,可选的参数
  • context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
  • local():可以直接将函数中所有的变量全部传给模板。当然这可能会传递一些多余的参数,有点浪费内存的嫌疑

 3.redirect()

 传递要重定向的一个硬编码的URL,也可以是一个完整的URL。

   语法:

def my_view(request):
    ...
    return redirect('/some/url/')
def my_view(request):
    ...
    return redirect('http://www.baidu.com/') 

四、CBV和FBV

 FBV(function base view):基于函数的view,就叫FBV

def add_class(request):
    if request.method == "POST":
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

 CBV(class base view):基于类的view,就叫CBV

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

  1. 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
  2. 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

使用步骤:

 ①使用前切记导入View,将创建的类继承自View

 from django.views import View

 ②该类会自动根据post请求与get请求自动分辨请求类型,选择对应的函数def get()或者def post()

 ③dispatch类似装饰器,可以在def get()或者def post()前后添加代码

     记得继承类obj=super().dispatch(request, *args, **kwargs),在其前后添加代码

 ④在路由调用视图函数时记得调用as_view()方法

from django.views import View
class AddPublish(View):
    def dispatch(self, request, *args, **kwargs):
        print(request)
        print(args)
        print(kwargs)
        # 可以写类似装饰器的东西,在前后加代码
        obj=super().dispatch(request, *args, **kwargs)
        return obj

    def get(self,request):
        return render(request,'index.html')
    def post(self,request):
        request
        return HttpResponse('post')

使用装饰器装饰CBV(dispatch)

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。

Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。

# 使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,这里我们可以手动改写dispatch方法,
这个dispatch方法就和在FBV上加装饰器的效果一样。
class Login(View): def dispatch(self, request, *args, **kwargs): print('before') obj = super(Login,self).dispatch(request, *args, **kwargs) print('after') return obj def get(self,request): return render(request,'login.html') def post(self,request): print(request.POST.get('user')) return HttpResponse('Login.post')

五、JsonResponse

切记:JsonResponse封装的方法只能是字典形式,否则会报错

如果一定要序列化列表,在JsonResponse内添加safe=false

原始手动自己打包json

def json_test(request):
    data = {'name':'xiaohei','age':18}
    import json
    return HttpResponse(json.dumps(data))

django方法JsonResponse

def json_test(request):
    data = {'name':'xiaohei','age':18}
    # import json
    # data_str = json.dumps(data)
    from django.http import JsonResponse
    return JsonResponse(data)

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

from django.http import JsonResponse

response = JsonResponse({'foo': 'bar'})
print(response.content)

b'{"foo": "bar"}'

默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。

response = JsonResponse([1, 2, 3], safe=False)

六、简单的文件上传方法

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
<form action="/upload/" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="userpassword">
    上传头像:<input type="file" name="photo">
    <input type="submit" value="开始上传">
</form>
</body>
</html>

urls

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^upload/',views.Upload.as_view())
]

python

from django.shortcuts import *
from django.views import View

# Create your views here.

class Upload(View):
    def get(self,request):
        return render(request,'test.html')
    def post(self,request):
        # print(request.FILES)
        # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
        filename = request.FILES["photo"].name
        # 在项目目录下新建一个文件
        with open(filename, "wb") as f:
            # 从上传的文件对象中一点一点读
            for chunk in request.FILES["photo"].chunks():
                # 写入本地文件
                f.write(chunk)
        return HttpResponse("上传OK")
原文地址:https://www.cnblogs.com/neymargoal/p/9594203.html