django视图层

HttpResponse,render,redirect


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


## render()
"""
render(request, template_name[, context])

参数:
    1、request:用于生成响应的请求对象,固定必须传入的第一个参数
    2、template_name:要使用的模板的完整名称,必须传入,render默认会去templates目录下查找模板文件
    3、context:可选参数,可以传入一个字典用来替换模块文件中的变量

render:返回html页面 并且在返回给浏览器之前还可以给html文件传值。
"""

## render简单内部原理
from django.shortcuts import render,redirect,HttpResponse,reverse

def index(request):
    from django.template import Template,Context
    res = Template('<h1>{{ user }}</h1>')
    con = Context({'user':{'username':'jason','password':123}})
    ret = res.render(con)
    print(ret)
    return HttpResponse(ret)


## redirect()
"""
返回重定向信息
"""
def my_view(request):
    ...
    return redirect('/some/url/')

# 重定向的地址也可以是一个完整的URL:
def my_view(request):
    ...
    return redirect('http://www.baidu.com/') 

JsonResponse对象


## 向前端返回json数据第一种方式
import json
def my_view(request):
    data=['egon','kevin']
    return HttpResponse(json.dumps(data, ensure_ascii=False) )

## 向前端返回json数据第二种方式
from django.http import JsonResponse
def ab_json(request):

    # 读源码掌握用法(JsonResponse内部调用json.dumps())
    return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

    # 当数据不是字典时要加safe
    # 不加safe报错信息:In order to allow non-dict objects to be serialized set the safe parameter to False.
    # l = [111,222,333,444,555]
    # return JsonResponse(l,safe=False)
    #默认safe=True代表只能序列化字典对象,safe=False代表可以序列化字典以外的对象

form表单上传文件

"""
form表单上传文件类型的数据
	1.method必须指定成post
	2.enctype必须换成multipart/form-data

## form.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    <p>username:<input type="text" name="username"></p>
    <p>file:<input type="file" name="file"></p>
    <input type="submit">
</form>
</body>
</html>
"""
def ab_file(request):
    if request.method == 'POST':
        # print(request.POST)  # 只能获取普通的简直对数据 文件不行
        print(request.FILES)  # 获取文件数据
        # <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}>
        file_obj = request.FILES.get('file')  # 文件对象
        print(file_obj.name)
        with open(file_obj.name,'wb') as f:
            for line in file_obj.chunks():  # 推荐加上chunks方法 其实跟不加是一样的都是一行行的读取
                f.write(line)

    return render(request,'form.html')

request对象方法

"""
request.method
request.POST
request.GET
request.FILES # 获取文件数据
request.body  # 原生的浏览器发过来的二进制数据  后面详细的讲
request.path  # 获取完整的url路径
request.path_info # 获取完整的url路径
request.get_full_path()  # 能过获取完整的url及问号后面的参数 
"""
print(request.path)  # /app01/ab_file/
print(request.path_info)  # /app01/ab_file/
print(request.get_full_path())  # /app01/ab_file/?username=jason

FBV与CBV

视图函数既可以是函数也可以是类


# FBV(function base view)
## 我们平常在写django时一直使用的都是FBV
def index(request):
  return HttpResponse('index')


# CBV(class base view)
## urls.py
urlpatterns = [
    # CBV路由
    url(r'^login/',views.MyLogin.as_view()) # 必须调用类下的方法as_view
]

## views.py
from django.views import View

## 能够直接根据请求方式的不同直接匹配到对应的方法执行
class MyLogin(View):
    def get(self,request):
          return render(request,'form.html')

    def post(self,request):
          return HttpResponse('post方法')

CBV源码剖析

## urls.py
urlpatterns = [
    # CBV路由
    url(r'^login/',views.MyLogin.as_view())
    ## 相当于 url(r'^login/',views.view)
]
"""
as_view()
    要么是被@staicmethod修饰的静态方法
    要么是被@classmethod修饰的类方法
"""


## views.py
from django.views import View

class MyLogin(View):
    def get(self,request):
        return render(request,'form.html')

    def post(self,request):
        return HttpResponse('post方法')


## 源码
class View(object):

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

    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs) # self = MyLogin(**initkwargs)
            ## 反射机制
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
            """
            对象属性查找顺序:先从对象自己找--->再去产生对象的类里面找--->之后再去父类找
            """
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
            ## 反射机制
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            """
            handler = getattr(自己写的类产生的对象,要获取的属性或方法,当属性或方法没有的时候就会用第三个参数)
            """
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

    def http_method_not_allowed(self, request, *args, **kwargs):
        logger.warning(
            'Method Not Allowed (%s): %s', request.method, request.path,
            extra={'status_code': 405, 'request': request}
        )
        return http.HttpResponseNotAllowed(self._allowed_methods())
原文地址:https://www.cnblogs.com/chenwenyin/p/12974262.html