zoukankan      html  css  js  c++  java
  • Django视图

    视图就是一个普通的Python函数,它接收从urls哪里的HttpRequest对象,返回的是HTML网页、重定向、404错误,XML文档或图像等任何东西。

    一般使用

    from django.http import HttpResponse
    # Create your views here.
    
    
    def index(request):
        return HttpResponse("<h1>hello world</h1>")
    
    

    例子,返回的是一个h1标签。

    接收参数

    当我们在路由设置参数时,在视图中应该要有对应的形参接收。

    # app/urls.py
    
    from django.urls import path
    from .views import index, article
    
    
    app_name = "app01"
    
    urlpatterns = [
    	# url中有个参数叫article_id,视图函数是article
        path("article/<int:article_id>", article, name="article")
    ]
    
    # app/views.py
    
    
    from django.http import HttpResponse
    # Create your views here.
    
    
    def article(request, article_id):
        return HttpResponse(f"article的id是{article_id}")
    
    

    返回

    视图函数返回各种数据,一般只需用到django.shortcuts下面的函数即可,该模块,为我们提供了很多快捷方便的类和方法,它们都很重要,使用频率很高。

    HTML页面

    使用django.shortcuts.render函数。

    from django.shortcuts import render
    
    
    def index(request):
        return render(request, "app01/index.html")
    
    

    render(request, template_name, context=None, content_type=None, status=None, using=None)

    必需参数:

    • request:视图函数处理的当前请求,封装了请求头的所有数据,其实就是视图参数request。
    • template_name:要使用的模板的完整名称或者模板名称的列表。如果是一个列表,将使用其中能够查找到的第一个模板。

    可选参数:

    • context:添加到模板上下文的一个数据字典。默认是一个空字典。可以将认可需要提供给模板的数据以字典的格式添加进去。这里有个小技巧,使用Python内置的locals()方法,可以方便地将函数作用域内的所有变量一次性添加进去。
    • content_type:用于生成的文档的MIME类型。 默认为DEFAULT_CONTENT_TYPE设置的值,也就是'text/html'。
    • status:响应的状态代码。 默认为200。
    • using:用于加载模板使用的模板引擎的NAME。

    template_name一般是在app/templates/app/下的html文件。多写一个"app"目的是区分不同的app中的同名html,因为假如settins的TEMPLATES中的APP_DIRS为True时,django会在app/templates下寻找html文件,所以要加上一层app名字。

    使用render本质就是:

    from django.http import HttpResponse
    from django.template import loader
    
    def my_view(request):
    
        t = loader.get_template('myapp/index.html')
        c = {'foo': 'bar'}
        return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
    

    使用locals()作为render的context参数,可以将视图中的全部局部变量给template。

    Json数据

    django返回json数据的方法有很多,下面介绍几种方法:

    1. 使用django.http.HttpRespone库+json
      直接使用json库序列化数据,然后使用HttpRespone返回数据,指定请求头Content-Type=application/json。
      序列化非 常用数据类型时,可以指定编码器(一个继承json.JSONEncoder的类,重写default方法)。

      from django.http import HttpResponse
      
      
      import json
      
      
      def index(request):
      	data = {
      		"name": "lczmx",
      		"age": 22,
      	}
      
      	return HttpResponse(json.dumps(data), content_type="application/json")
      
      
    2. 使用django.http.HttpRespone库+django.core.serializers
      此方法可以很好的序列化QuerySet对象。

      def index(request):
      	questions = Question.objects.all()
      	data = serializers.serialize("json", queryset=questions)
      	return HttpResponse(data, content_type="application/json")
      

      serializers.serialize的第一个参数是格式,第二个参数是queryset数据。
      更多见官方文档:序列化 Django 对象

    3. 使用django.http.JsonResponse

      class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)
      

      JsonResponse是一个 HttpResponse 子类,帮助创建一个 JSON 编码的响应。它继承了它的超类的大部分行为,但有一些不同:
      其默认的 Content-Type 头设置为 application/json。

      • 第一个参数 data 应该是 dict 实例。如果 safe 参数设置为 False (见下文),它可以是任何 JSON 可序列化的对象。
      • encoder,默认为 django.core.serializers.json.DjangoJSONEncoder,将用于序列化数据。。
      • safe 布尔参数默认为 True。如果它被设置为 False,任何对象都可以被传递到序列化中(否则只允许 dict 实例)。如果 safe 为 True,而第一个参数是一个非 dict 对象,则会引发一个 TypeError。
      • json_dumps_params 参数是一个关键字参数的字典,用来传递给 json.dumps() 调用,用于生成响应。
      from django.http import JsonResponse
      
      
      
      def index(request):
      	data = {
      		"name": "lczmx",
      		"age": 22,
      	}
      
      	return JsonResponse(data)
      

    跳转页面

    跳转页面使用redirect进行页面跳转。

    redirect(to, args, permanent=False, *kwargs)
    

    根据传递进来的url参数,返回HttpResponseRedirect。

    参数to可以是:

    • 一个模型实例:将调用模型的get_absolute_url()函数,反向解析出目的url;
    • URL的name名称:可能带有参数:reverse()将用于反向解析url;
    • 一个绝对的或相对的URL:将原封不动的作为重定向的目标位置。
      默认情况下是临时重定向,如果设置permanent=True将永久重定向。

    例子:

    # urls.py
    from django.urls import path
    from .views import index, article
    
    
    app_name = "app01"
    
    urlpatterns = [
        path("index/", index, name="index"),
        path("article/<int:article_id>", article, name="article")
    ]
    
    # views.py
    
    from django.http import HttpResponse
    from django.shortcuts import redirect
    # Create your views here.
    
    
    def index(request):
        return HttpResponse("index page")
    
    
    def article(request, article_id):
        if article_id > 123:
            return redirect("app01:index")
        return HttpResponse(f"article的id是{article_id}")
    	
    

    错误信息

    django实现了一些状态码以4和5开头的HttpRespone子类,点击查看。
    假如没有我们需要的,可以自定义响应类,只需要继承HttpRespone类,然后指定status_code属性的值即可。

    from http import HTTPStatus
    from django.http import HttpResponse
    
    
    class HttpResponseNoContent(HttpResponse):
        status_code = HTTPStatus.NO_CONTENT
    	
    

    404
    为了方便,django提供了django.http.Http404异常类,在视图中主动抛出这个异常时,Django 会捕捉到它并且返回标准的错误页面,连同 HTTP 错误代码 404 。

    from django.http import Http404
    
    
    def article(request, article_id):
        if article_id > 123:
            raise Http404("page not fund")
        return HttpResponse(f"article的id是{article_id}")
    
    

    虽然可以返回404页面,但是这是django内置的404页面,在实际使用中,需要换成我们自己的。
    需要注意的是,要使用自定义的404html,需要将settings文件中的DEBUG设为False。

    由于当你raise了Http404后:
    django会做一下动作:

    1. django.conf.urls.handler404,这相当于一个urls文件:
    # __init__文件的内容
    from django.urls import include, re_path
    from django.views import defaults
    
    __all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'url']
    
    handler400 = defaults.bad_request
    handler403 = defaults.permission_denied
    handler404 = defaults.page_not_found
    handler500 = defaults.server_error
    # ...
    
    1. 使用django.views.defaults.page_not_found()视图
    2. 判断是否自定义了404.html,
      • 如果有(查找的是template,和一般的一样),输出该HTML文件
      • 如果没有,输出默认的404提示信息

    所以我们要自定以404页面有两个方法:

    1. 使用默认的django.views.defaults.page_not_found()视图,然后再自己在template中创建404.html文件。
    2. 自定义处理404的视图

    第一种方法:

    1. 在template创建一个404页面
      注意要配置好settings.TEMPLATES的DIRS或APP_DIRS。

    2. 使用静态的页面或使用django的模板引擎展示更多详细信息。
      简化django的page_not_found视图,发现其主要做了以下内容:

      template.render(context = {
      	'request_path': quote(request.path),
      	'exception': exception.args[0]}, request)
      
      # quote为urllib.parse.quote
      # 作用是对url进行url编码
      

      因此我们可以在404.html中利用模板引擎拿到context。其中:request_path是你当前的url,exception是异常类的信息,比如这样定义404.html:

      <!DOCTYPE html>
      <html lang="en">
      <head>
      	<meta charset="UTF-8">
      	<title>PageNotFound</title>
      </head>
      <body>
      <h1>404页面</h1>
      <p>不存在的链接:{{ request_path }}</p>
      <p>提示:{{ exception }}</p>
      </body>
      </html>
      

    第二种方法:
    步骤:

    1. 根urls中,定义handler404,使其的值为自己处理404的视图
    2. 完成404视图的编写
      比如:
    # 根urls.py
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path("app01/", include("app01.urls")),
    ]
    handler404 = "app01.views.page_not_found"
    # 看有些博客用的是
    # handler404 = views.page_not_found # handler404直接等于一个视图函数
    # 但官方的例子是使用字符串的
    
    
    # views.py
    @requires_csrf_token
    def page_not_found(request, exception):
    	# ....
    	# ....
        return render(request, 'errors/404.html')
    

    注意:一定要在根定义handler404,否则会老是用默认的!!!(我用的是django3.0.1,其他版本django不知道)

    关于其他诸如400、403等页面,其自定义方法也是这样,不过是把handler的视图状态码.html换成对应的。对于前种方法,官方给了一些的例子:自定义报错视图

    HttpRequest对象

    关于HttRequest的各种属性见官方文档:HttpRequest

    一些常用的(表中的request指定的HttpRequest对象):

    属性 说明
    request.scheme 协议http or https
    request.path 返回完整路径,形如:"/app/index"
    request.path_info 路径的路径信息部分
    request.method HTTP 方法,大写
    request.GET get参数,属于QueryDict对象
    request.POST post参数, 属于QueryDict对象
    request.COOKIES 一个包含所有 cookies 的字典。键和值是字符串。
    request.FILES 一个类似字典的对象,包含所有上传的文件
    request.headers 请求中的所有HTTP头,是一个不区分大小写的类似字典的对象

    取参数

    这里的取参数指的是取get或者post的参数,由于request.GET和request.POST对属于QueryDict对象,所以先了解一下django.http.request.QueryDict对象:

    1. QueryDict是对http请求数据的封装
    2. QueryDIct是dict的子类,所以很多使用方法和字典一样
    3. 一般只需要使用get方法即可(和字典的一样用),其他方法点击这里查看。

    所以取get和post参数:

    def t(request):
        if request.method == "GET":
            print(request.GET.get("name"))
            print(request.GET.get("age"))
        elif request.method == "POST":
            print(request.POST.get("name"))
            print(request.POST.get("age"))
        return HttpResponse("ok!")
    

    注意使用POST方式提交时,要在form表单中加上{% csrf_token %}标签,至于使用ajax提交post请求,见后文大标题

    HttpRespone对象

    HttpResponse对象则是你想要返回给浏览器的数据的封装。
    我们编写的每个视图都要实例化、填充和返回一个HttpResponse对象。也就是函数的return值。
    HttpRespone可以传递一个一个string、bytes或者memoryview或可迭代对象。

    常用属性

    属性 说明
    content 响应的内容。bytes类型。
    charset 编码的字符集。 如果没指定,将会从content_type中解析出来。
    status_code 响应的状态码,比如200。

    常用方法

    方法 说明
    has_header(header) 检查头部中是否有给定的名称(不区分大小写),返回True或 False。
    setdefault(header, value) 当该头字段不存在时,设置一个头部
    delete_cookie() 删除一个Cookie,参数见下文

    更多点击这里查看

    设置与删除响应头字段

    from django.http import HttpResponse
    
    
    def index(request):
        response = HttpResponse()
        # 通过中括号设置值
        response["name"] = "lczmx"
        response["age"] = 20
        response.setdefault("age", 22)
        # 使用del删除头字段
        # key不存在时,不会报错
        del response["name"]
        return response
    	
    

    cookie与session

    HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。为了给客户端们一个通行证,W3C组织提出了Cookie。
    Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务 器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
    由于Cookie存在不安全、大小有限制、受制于同源策略等缺点,所以除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。

    下面的内容需要注意方法的对象是respone还是request

    设置Cookie
    使用HttpResponse对象的set_cookie方法设置一个 cookie。参数与 Python 标准库中的 Morsel cookie 对象相同:

    HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None)
    
    • key是cookie的键
    • value是cookie的值
    • max_age是cookie的生存周期
      以秒为单位。如果设为None,浏览器开启期间保持,关闭后一同删除。
    • expires是到期时间
      格式为 "Wdy, DD-Mon-YY HH:MM:SS GMT" 的字符串,或者是 UTC 的 datetime.datetime 对象。
      如果 expires 是一个 datetime 对象,将计算 max_age。
      如:datetime.datetime.utcnow() + datetime.timedelta(days=7)
    • domain用于设置跨域的Cookie
      例如domain=".lawrence.com"将设置一个www.lawrence.com、blogs.lawrence.com和calendars.lawrence.com都可读的Cookie。 否则,Cookie将只能被设置它的域读取。
    • secure是否支持https,为True时支持https
    • httponl,为True时阻止客户端的js代码访问cookie

    注意cookie不要超过 4096 字节

    获取Cookie
    使用HttpRequest.COOKIES对象的get方法:
    如:

    request.Cookie.get("key")
    

    删除Cookie
    HttpResponse.delete_cookie(key, path='/', domain=None, samesite=None)
    删除给定键的 cookie。如果键不存在,则静默失败。

    • key是键
    • path和domain应该与set_cookie()中使用的值相同,否则Cookie不会删掉

    例子

    from django.http import HttpResponse
    from django.shortcuts import render, redirect
    from django.urls import reverse
    
    
    
    def auth_login(req_func):
        """
        用于检验登录信息的装饰器
        :param req_func:
        :return:
        """
        def wap(*args, **kwargs):
            req = args[0]
    		# 获取cookie
            if req.COOKIES.get("username") != "lczmx":
                url = reverse("app01:login") + "?next=%s" % req.path
                return redirect(url)
            return req_func(*args, **kwargs)
        return wap
    
    
    @auth_login
    def index(request):
        return render(request, "app01/index.html")
    
    
    def login(request):
        next_url = request.GET.get("next")
    
        if request.method == "GET":
            return render(request, "app01/login.html", {"next_url": next_url})
        elif request.method == "POST":
            username = request.POST.get("username")
            pwd = request.POST.get("password")
            if username == "lczmx" and pwd == "123456":     # 假装验证了
                ret = redirect(next_url)
    			# 设置cookie
                ret.set_cookie("username", "lczmx")
            else:
                ret = HttpResponse("验证失败")
            return ret
    
    
    def logout(request):
        ret = HttpResponse("success")
    	# 删除cookie
        ret.delete_cookie("username")
        return ret
    	
    

    Session

    由于django的session依赖中间件:SessionMiddleware,所以要用session的时候不要去掉 MIDDLEWARE中的django.contrib.sessions.middleware.SessionMiddleware

    session操作都要使用到HttpRequest.session对象,这是一个可读可写的,类似字典的对象,代表当前会话。

    设置Session

    request.session["name"] = "lczmx"
    

    获取Session

    request.session.get("lczmx")
    

    删除Session

    del request.session["lczmx"]
    

    [更多关于session的方法【包括session的保存方式】(https://docs.djangoproject.com/zh-hans/3.2/topics/http/sessions/#using-sessions-in-views)

    设置session的保存时间

    request.set_expiry(value)
    

    为会话设置过期时间。你可以传递很多不同值:

    • 如果 value 是整型,会话将在闲置数秒后过期。比如,调用 request.session.set_expiry(300) 会使得会话在5分钟后过期。
    • 如果 value 是一个 datetime 或 timedelta 对象,会话将在指定的 date/time 过期。注意,如果你正在使用 PickleSerializer ,那么 datetime 和 timedelta 的值只能序列化。
    • 如果 value 是 0 ,则当浏览器关闭后,用户会话 cookie 将过期。
    • 如果 value 是 None ,会话会恢复为全局会话过期策略。
      出于过期目的,读取会话不被视为活动。会话过期时间会在会话最后一次修改后开始计算。

    django内置的装饰器

    部分内容转载于这里:常用装饰器应用场景及正确使用方法

    django.views.decorators.http

    from django.views.decorators.http import require_http_methods
    
    @require_http_methods(["GET", "POST"])
    def my_view(request):
        # I can assume now that only GET or POST requests make it this far
        # ...
        pass
    

    一些类似的装饰器:
    require_GET:装饰器可以要求视图只接受 GET 方法。
    require_POST:装饰器可以要求视图只接受 POST 方法。
    require_safe:装饰器可以要求视图只接收 GET 和 HEAD 方法。这些方法通常被认为是安全的,因为它们除了检索请求的资源外,没有特别的操作。

    django.contrib.auth.decorators

    权限验证

    1. @login_required
      @login_required是Django最常用的一个装饰器。其作用是在执行视图函数前先检查用户是否通过登录身份验证,并将未登录的用户重定向到指定的登录url。其中login_url是可选参数。如果不设置,默认login_url是settings.py里设置的LOGIN_URL。

      from django.contrib.auth.decorators import login_required
      
      @login_required(login_url='/accounts/login/')
      def my_view(request):
        ...
      

      @login_required还可以一个可选参数是redirect_field_name, 默认值是'next'。

      from django.contrib.auth.decorators import login_required
      
      
      
      @login_required(redirect_field_name='my_redirect_field')
      
      def my_view(request):
      
      	...
      

      注意:

      login_required装饰器不会检查用户是否是is_active状态。如果你想进一步限制登录验证成功的用户对某些视图函数的访问,你需要使用更强大的@user_passes_test装饰器。

    2. @user_passes_test

      @user_passes_test装饰器的作用是对登录用户对象的信息进行判断,只有通过测试(返回值为True)的用户才能访问视图函数。不符合条件的用户会被跳转到指定的登录url。

      @user_passes_test装饰器有一个必选参数,即对用户对象信息进行判断的函数。该函数必需接收user对象为参数、返回一个布尔值。其与login_required类似,@user_passes_test还有两个可选参数(login_url和redirect_field_name),这里就不多讲了。

      user_passes_test(func[,login_url=None, redirect_field_name=REDIRECT_FIELD_NAME]) 
      

      下例中@user_passes_test装饰器对用户的email地址结尾进行判断,会把未通过测试的用户会定向到登录url。试想一个匿名用户来访问,她没有email地址,显然不能通过测试,登录后再来吧。

      from django.contrib.auth.decorators import user_passes_test
      
      
      
      def email_check(user):
      	return user.email.endswith('@example.com')
      
      
      @user_passes_test(email_check)
      def my_view(request):
      	...
      

      如果需要加可选参数,可以按如下方式使用。

      @user_passes_test(email_check, login_url='/login/'):
      def my_view(request):
      	...
      

      注意:

      @user_passes_test不会自动的检查用户是否是匿名用户,但是@user_passes_test装饰器还是可以起到两层校验的作用。一来检查用户是否登录,二来检查用户是否符合某些条件,无需重复使用@login_required装饰器。

      我们如果只允许is_active的登录用户访问某些视图,我们现在可以使用@user_passes_test装饰器轻松地解决这个问题,如下所示:

      from django.contrib.auth.decorators import user_passes_test
      
      @user_passes_test(lambda u: u.is_active)
      def my_view(request):
      	...
      
    3. @permission_required

      @permission_required装饰器的作用是检查用户用户是否有特定权限,第一个参数perm是权限名,为必选, 第二个参数login_url为可选。

      permission_required(perm[, login_url=None, raise_exception=False]) 
      
      

      下例检查用户是否有polls.can_vote的权限,没有的话定向至login_url。如果你设置了raise_exception=True, 会直接返回403无权限的错误,而不会跳转到登录页面。那么问题来了,我们需要先使用@login_required来验证用户是否登录,再使用@permission_required装饰器来查看登录用户是否具有相关权限吗? 答案是不需要。如果一个匿名用户来访问这个视图,显然该用户没有相关权限,会自动定向至登录页面

      from django.contrib.auth.decorators import permission_required
      
      
      
      @permission_required('polls.can_vote', login_url='/login/')
      def my_view(request):
      	...
      

    django.views.decorators.cache

    这个模块下的装饰器适用于缓存的,缓存是Django装饰器很重要的一个应用场景。下面我们来看几个主要的缓存装饰器。注意: 使用以下装饰器的前提是你已经对缓存进行了相关设置。

    1. @cache_page

      该装饰器可以接收缓存的时间作为参数,比如下例缓存页面15分钟。

      
      from django.views.decorators.cache import cache_page
      
      
      @cache_page(60 * 15)
      def my_view(request):
      	...
      
      
      
    2. @cache_control

      通常用户将会面对两种缓存: 他或她自己的浏览器缓存(私有缓存)以及他或她的提供者缓存(公共缓存)。 公共缓存由多个用户使用,而受其它人的控制。 这就产生了你不想遇到的敏感数据的问题,比如说你的银行账号被存储在公众缓存中。 因此,Web 应用程序需要以某种方式告诉缓存那些数据是私有的,哪些是公共的。cache_control装饰器可以解决这个问题。

      
      from django.views.decorators.cache import cache_control
      
      @cache_control(private=True)
      def my_view(request):
      	...
      

      该修饰器负责在后台发送相应的 HTTP 头部。还有一些其他方法可以控制缓存参数。 例如, HTTP 允许应用程序执行如下操作:

      • 定义页面可以被缓存的最大时间。

      • 指定某个缓存是否总是检查较新版本,仅当无更新时才传递所缓存内容。

      在 Django 中,可使用 cache_control 视图修饰器指定这些缓存参数。 在下例中, cache_control 告诉缓存对每次访问都重新验证缓存并在最长 3600 秒内保存所缓存版本。

      from django.views.decorators.cache import cache_control
      
      
      @cache_control(must_revalidate=True, max_age=3600)
      def my_view(request):
      	...
      
      

      cache_control中,任何合法的Cache-Control HTTP 指令都是有效的。下面是完整列表:

      public=True
      private=True
      no_cache=True
      no_transform=True
      must_revalidate=True
      proxy_revalidate=True
      max_age=num_seconds
      s_maxage=num_seconds
      
    3. @vary_on_headers

      缺省情况下,Django 的缓存系统使用所请求的路径(如blog/article/1)来创建其缓存键。这意味着不同用户请求同样路径都会得到同样的缓存版本,不考虑客户端user-agent, cookie和语言配置的不同, 除非你使用Vary头部通知缓存机制需要考虑请求头里的cookie和语言的不同。
      要在 Django 完成这项工作,可使用便利的 vary_on_headers视图装饰器。例如下面代码告诉Django读取缓存数据时需要同时考虑User-Agent和Cookie的不同。与此类似的装饰器还有@vary_on_cookie

      
      from django.views.decorators.vary import vary_on_headers
      
      
      @vary_on_headers('User-Agent', 'Cookie')
      def my_view(request):
      	...
      
      
      
    4. @never_cache

      如果你想用头部完全禁掉缓存, 你可以使用@never_cache装饰器。如果你不在视图中使用缓存,服务器端是肯定不会缓存的,然而用户的客户端如浏览器还是会缓存一些数据,这时你可以使用never_cache禁用掉客户端的缓存。

      from django.views.decorators.cache import never_cache
      
      
      @never_cache
      def myview(request):
      	# ...
      
      

    其它常用装饰器

    @method_decorator
    前面的案例中,我们的装饰器都是直接使用在函数视图上的。如果需要在基于类的视图上使用装饰器,我们需要使用到@method_decorator这个装饰器, 它的作用是将类伪装成函数方法。@method_decorator第一个参数一般是需要使用的装饰器名。

    from django.contrib.auth.decorators import login_required
    from django.utils.decorators import method_decorator
    from django.views.generic import TemplateView
    
    
    
    @method_decorator(login_required, name='dispatch')
    class ProtectedView(TemplateView):
        template_name = 'secret.html'
    
    

    常用自定义装饰器

    关于一些自定义装饰器,见:详解Django中六个常用的自定义装饰器

    使用多重装饰器

    你可以在一个函数或基于类的视图上使用多重装饰器,但一定要考虑装饰器执行的先后顺序。比如下例中会先执行@never_cache, 再执行@login_required

    
    from django.contrib.auth.decorators import login_required
    from django.utils.decorators import method_decorator
    
    from django.views.decorators.cache import never_cache
    
    
    
    @method_decorator(never_cache, name='dispatch')
    
    @method_decorator(login_required, name='dispatch')
    class ProtectedView(TemplateView):
        template_name = 'secret.html'
    
    class ProtectedView(TemplateView):
        template_name = 'secret.html'
    
    

    上例等同于:

    decorators = [never_cache, login_required]
    
    @method_decorator(decorators, name='dispatch')
    class ProtectedView(TemplateView):
        template_name = 'secret.html'
    

    上传及下载文件

    见:https://docs.djangoproject.com/zh-hans/3.2/topics/http/file-uploads/

    FBV及CBV

    FBV是指以函数的形式定义视图,而CBV是指以类的形式定义视图。
    二者各有优点,FBV胜在灵活、简便,而CBV在某些场景中可以极大地降低代码复用。
    要使用类视图,主要有一下几个要点:

    1. views.py中自定义一个继承django.views.View的类
    2. 为自定义类添加请求方法的方法,即get请求就添加get方法
    3. 在urls.py中,指定path的第二个参数为类名.as_view()
    # views.py
    from django.views import View
    
    
    class CView(View):
        def get(self, request):
            return render(request, "app01/index.html")
    
    # urls.py
    from .views import CView
    app_name = "app01"
    
    urlpatterns = [
        path("cview/", CView.as_view(), name="cview"),
    ]
    
    

    除了django.views.View外,django还有一些内置的类视图,点击查看:内置基于类的视图 API

    本文来自博客园,作者:忞翛,转载请注明原文链接:https://www.cnblogs.com/lczmx/p/14938831.html

  • 相关阅读:
    HDU 1754 I Hate It (线段树)
    HDU 1394 Minimum Inversion Number (树状数组)
    天梯赛 L2-012 关于堆的判断 (二叉树)
    HDU 1166 敌兵布阵 (树状数组 单点修改+区间查询)
    [leetcode-77-Combinations]
    [leetcode-101-Symmetric Tree]
    [leetcode-21-Merge Two Sorted Lists]
    [leetcode-109-Convert Sorted List to Binary Search Tree]
    [leetcode-507-Perfect Number]
    [leetcode-537-Complex Number Multiplication]
  • 原文地址:https://www.cnblogs.com/lczmx/p/14938831.html
Copyright © 2011-2022 走看看