zoukankan      html  css  js  c++  java
  • Django的View(视图)

    Django的View(视图)

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

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

    无论视图本身包含什么逻辑,都要返回响应。

    代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。

    为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为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使用请求和响应对象来通过系统传递状态。

    当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的源数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。

    每个视图负责返回一个HttpResponse对象。



    FBV和CBV



    Request对象和Response对象

    request对象

    当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。

    Django会将这个对象自动传递给响应的视图函数

    一般视图函数约定俗成地使用 request 参数承接这个对象。


    请求相关的常用值

    path_info: 返回用户访问url,不包括域名

    method: 请求中使用的HTTP方法的字符串表示,全大写表示

    GET 包含所有HTTP GET参数的类字典对象

    POST 包含所有HTTP POST参数的类字典对象

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

    属性

    所有的属性应该被认为是只读的,除非另有说明。

    展开查看
    
    HttpRequest.method
      一个字符串,表示请求使用的HTTP 方法。必须使用大写。
      例如:"GET"、"POST"
    HttpRequest.GET 
      一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象
    HttpRequest.POST
      一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。
      POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。
       因此,不应该使用 if request.POST  来检查使用的是否是POST 方法;应该使用 if request.method == "POST" 
      另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。    
      ;
    

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

    request.POST.getlist("hobby")
    


    Response对象

    与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。

    我们写的每个视图都需要实例化,填充和返回一个HttpResponse。

    HttpResponse类位于django.http模块中。

    使用

    传递字符串

    from django.http import HttpResponse
    response = HttpResponse("Here's the text of the Web page.")
    response = HttpResponse("Text only, please.", content_type="text/plain")
    

    Django shortcut functions

    render()

    结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。

    request: 用于生成响应的请求对象。

    template_name:要使用的模板的完整名称,可选的参数

    context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

    content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'

    status:响应的状态码。默认为200。   

    useing: 用于加载模板的模板引擎的名称。

    一个简单的例子:

    展开查看
    
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('name')
            password = request.POST.get('pwd')
            # print(username,password)
            res = models.User.objects.filter(name=username)
            if res:
                user_obj = res.first()
                if user_obj.pwd == password:
                    return HttpResponse("登陆成功")
                else:
                    return HttpResponse("密码错误")
            return HttpResponse("用户不存在")
        return render(request, 'login.html')
    

    redirect()

    参数可以是:

    • 一个模型:将调用模型的get_absolute_url() 函数
    • 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
    • 一个绝对的或相对的URL,将原封不动的作为重定向的位置。

    默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。

    示例:

    你可以用多种方式使用redirect() 函数。

    传递一个视图的名称

    def my_view(request):
        ...
        return redirect('some-view-name', foo='bar')
    

    传递要重定向到的一个具体的网址

    def my_view(request):
        ...
        return redirect('/some/url/')
    

    当然也可以是一个完整的网址

    def my_view(request):
        ...
        return redirect('http://example.com/')
    

    默认情况下,redirect() 返回一个临时重定向。以上所有的形式都接收一个permanent 参数;如果设置为True,将返回一个永久的重定向:

    def my_view(request):
        ...
        object = MyModel.objects.get(...)
        return redirect(object, permanent=True)  
    

    ## JsonResponse
    from django.http import JsonResponse
    def xxx(request):
        user_dict = {'username':'无敌得我','password':'123'}
        # json_str = json.dumps(user_dict,ensure_ascii=False)
        # return HttpResponse(json_str)
        l = [1,2,3,4,5,6,7,8,9,]
        # return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
        return JsonResponse(l,safe=False)  # 序列化非字典格式数据 需要将safe改为False
    
    前后端数据交互
    form表单上传文件
    action
    method   post
    enctype  formdata
    

    # CBV与FBV

    django的视图层由两种形式构成:FBV和CBV

    1、FBV基于函数的视图(Function base view)

    FBV的模式就是在Django的路由映射表里进行url和视图函数的关联

    from django.http import HttpResponse
    def my_view(request):
       if request.method == 'GET':
          return HttpResponse('OK')
    
    

    2、CBV基于类的视图(Class base view)

    from django.views import View
    
    class MyLogin(View):
    	def get(self,request):
    		return render(request,'login.html')
    	def post(self,request):
    		return HttpResponse('我是类里面的post方法')
    
    url(r'^login/',views.MyLogin.as_view())
    

    朝login提交get请求会自动执行MyLogin里面的get方法

    而提交post请求也会自动执行MyLogin里面的post方法

    在路由匹配完成后,会执行类中的as_view方法。

    类中并没有定义as_view方法,由于继承自Django的View,所以会执行Django的View类中的as_view方法

    从View的源码可以看出,在View类中,先定义了http请求的八种方法

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    

    Django的url是将一个请求分配给可调用的函数的,而不是一个class。

    针对这个问题, view提供了一个as_view()类方法,调用这个方法,会创建一个类的实例

    然后通过实例调用dispatch()方法

    在dispatch方法中,把request.method转换为小写再判断是否在定义的http_method_names中,如果request.method存在于http_method_names中,则使用getattr反射的方式来得到handler

    dispatch()方法会根据request的method的不同调用相应的方法来处理request,再执行CBV类中的方法并返回

    由此,可以知道如果在Django项目中使用CBV的模式,实际上调用了getattr的方式来执行获取类中的请求方法对应的函数

    结论:

    CBV基于反射实现根据请求方式不同,执行不同的方法



    Django文件传输

    利用Django实现文件上传并且保存到指定路径下,其实并不困难,完全不需要用到django的forms,也不需要django的models,就可以实现,下面开始实现。

    第一步:在模板文件中,创建一个form表单,需要特别注意的是,在有文件上传的form表单中,method属性必须为post,而且必须指定它的enctype为"multipart/form-data",表明不对字符进行编码,具体的代码如下:

    {% extends 'home.html' %}
    
    {% block content %}
    
        <form enctype="multipart/form-data" action="" method="post">
            <input type="file" name="file">
            <input type="submit">
        </form>
    
    {% endblock %}
    

    第二步:设置urls.py文件,指定相应的视图函数进行处理

    第三步:最重要的,在视图函数中做处理

    def upload(request):
            """
        保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
        但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
        :param request: 
        :return: 
        """
        if request.method == 'POST':
            # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
            filename = request.FILES['file'].name
            # 在项目目录下新建一个文件
            with open(filename, 'wb') as f:
                # 从上传的文件对象中一点一点读
                for chunk in request.FILES['file'].chunks():
                    # 写入本地文件
                    f.write(chunk)
            return HttpResponse('ok')
    
        return render(request, 'upload.html')
    
  • 相关阅读:
    [JSOI2007][BZOJ1031] 字符加密Cipher|后缀数组
    leetcode Flatten Binary Tree to Linked List
    leetcode Pascal's Triangle
    leetcode Triangle
    leetcode Valid Palindrome
    leetcode Word Ladder
    leetcode Longest Consecutive Sequence
    leetcode Sum Root to Leaf Numbers
    leetcode Clone Graph
    leetcode Evaluate Reverse Polish Notation
  • 原文地址:https://www.cnblogs.com/kai-/p/12150983.html
Copyright © 2011-2022 走看看