5.Django视图系统

Django视图系统

  1. Django的View

    • 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
    • 响应可以是网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
    • 无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。
    • 简而言之,视图,就是你写业务逻辑的地方。

  1. 一个简单的视图示例

    • 下面是一个在views.py中以HTML文档形式返回当前日期和时间的视图:

      from django.http import HttpResponse
      import datetime
      
      def current_datetime(request):
          now = datetime.datetime.now()
          html = "<html><body>It is now %s.</body></html>" % now
          return HttpResponse(html)
      
    • 让我们来逐行解释下上面的代码:

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

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

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

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

      • Django使用请求和响应对象来通过系统传递状态。当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。每个视图负责返回一个HttpResponse对象。


  1. FBV和CBV

    • FBV:基于函数写的view称为FBV。

      def register(request):
          '''
          这是一个注册页面的函数
          :param request:
          :return:
          '''
          if request.method == 'POST':
              # 用户提交注册信息
              username = request.POST.get('username', None)
              # 通过models.UserInfo.objects对象在数据库中创建这条记录
              models.UserInfo.objects.create(name=username)
              # 数据创建成功后直接跳转到user_list页面
              return redirect('/user_list/')
          # 如果不为POST,则执行下面的语句
          return render(request, 'register.html')
      
    • CBV:基于类写的view称为CBV。

      from django.views import View
      
      class Registrer(View):    # 需要继承View
          
          def get(self, request):
              return render(request, 'register.html')
      
          def post(self, request):
              username = request.POST.get('username', None)
              # 通过models.UserInfo.objects对象在数据库中创建这条记录
              models.UserInfo.objects.create(name=username)
              # 数据创建成功后直接跳转到user_list页面
              return redirect('/user_list/')
      

      需要注意的是,若使用CBV,urls.py中调用类的时候必须加上.as_Views()

      # urls.py中
      from django.contrib import admin
      from django.urls import path
      from app import views
      
      urlpatterns = [
          # ......
          path('register/', views.Register.as_View()),
          # ......
      ]
      

  1. 视图装饰器

    • Django 提供很多装饰器,它们可以为视图支持多种 HTTP 特性。查看 装饰类 来了解如何在基于类的视图中使用这些装饰器。

    • 允许的 HTTP 方法

      • 在 django.views.decorators.http 中的装饰器可以用来根据请求方法来限制对视图的访问。如果条件不满足,这些装饰器将返回 django.http.HttpResponseNotAllowed 。

      • require_http_methods(request_method_list)装饰器可以要求视图只接受特定的请求方法。

        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 方法。这些方法通常被认为是安全的,因为它们除了检索请求的资源外,没有特别的操作。

      注解

      Web 服务器自动删除对 HEAD 请求的相应内容,并保持头部不变,所以你可以像处理视图里的 GET 请求一样处理 HEAD 请求。因为一些软件依赖 HEAD 请求(比如链接检测器),因此你需要使用 require_safe 而不是 require_GET 。


  1. Request对象和Response对象

    • Request对象(HttpRequest的对象)

      • 当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。并且会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。在视图函数中,接收的request常用的属性如下:

        • request.path_info:返回用户访问的url,不包括域名、IP、端口和参数。

        • request.method:所使用的请求方法(GET还是POST),全大写表示。

        • request.GET:以字典的形式获取HTTP信息中的GET参数。

        • request.POST:以字典的形式获取HTTP信息中的POST参数。

        • request.body: 请求体,byte类型 request.POST的数据就是从body里面提取到的。

        • request.scheme:以字符串形式获取请求的方式(http或https)。

        • request.body:以byte形式获取请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。

        • request.path:返回用户访问的url,不包括域名、IP、端口和参数。

        • request.COOKIES:一个标准的Python 字典,包含所有的cookie。键和值都为字符串。

        • request.FILES:一个类似于字典的对象,包含所有的上传文件信息。

        • request.META:一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器。

          • CONTENT_LENGTH:请求的正文的长度(是一个字符串)

          • CONTENT_TYPE:请求的正文的MIME 类型

          • HTTP_ACCEPT:响应可接收的Content-Type

          • HTTP_ACCEPT_ENCODING:响应可接收的编码。

          • HTTP_ACCEPT_LANGUAGE:响应可接收的语言。

          • HTTP_HOST:客服端发送的HTTP Host 头部。

          • HTTP_REFERER:Referring 页面。

          • HTTP_USER_AGENT:客户端的user-agent 字符串。

          • QUERY_STRING:单个字符串形式的查询字符串(未解析过的形式)。

          • REMOTE_ADDR:客户端的IP 地址。

          • REMOTE_HOST:客户端的主机名。

          • REMOTE_USER:服务器认证后的用户。

          • REQUEST_METHOD:一个字符串,例如"GET" 或"POST"。

          • SERVER_NAME:服务器的主机名。

          • SERVER_PORT:服务器的端口(是一个字符串)。

            从上面可以看到,除 CONTENT_LENGTHCONTENT_TYPE之外,请求中的任何 HTTP 首部转换为 META 的键时,都会将所有字母大写并将连接符替换为下划线最后加上HTTP_前缀。

        • request.user:一个 AUTH_USER_MODEL 类型的对象,获取当前登录的用户。

        • request.session:一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django启用会话的支持时才可用。

      • request中常用的方法:

        • request.get_host():根据从HTTP_X_FORWARDED_HOST(如果打开 USE_X_FORWARDED_HOST,默认为False)和 HTTP_HOST 头部信息返回请求的原始主机。如果这两个头部没有提供相应的值,则使用SERVER_NAMESERVER_PORT,在PEP 3333 中有详细描述。USE_X_FORWARDED_HOST是一个布尔值,用于指定是否优先使用 X-Forwarded-Host 首部,仅在代理设置了该首部的情况下,才可以被使用。
        • request.get_full_path():不同于request.path_info,虽然不包括域名、IP、端口,但会包含参数。
        • request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None):返回签名过的Cookie 对应的值,如果签名不再合法则返回django.core.signing.BadSignature
        • request.is_secure():如果请求时是安全的,则返回True;即请求通是过 HTTPS 发起的。
        • request.is_ajax():如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串XMLHttpRequest。大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。

  • Response对象

    • 与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse。HttpResponse类位于django.http模块中。

  • JsonResponse对象

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

      from django.http import JsonResponse
      
      def get_josn():
       data = {'foo': 'bar'}
       response = JsonResponse(data)
          # 默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。response = JsonResponse(data, safe=False)
       return response
      
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342