VIEW 视图

 FBV    CBV

 Django中请求处理方式有两种: FBV和CBV

FBV: function base views    在试图里使用函数处理请求

# url对应关系:url(r'^add_publisher/', views.add_publisher),
from django.views import View

def add_publisher(request):
    '''新增出版社数据'''
    if request.method == 'POST':
        # 获取提交的数据(括号内为input的name属性值),没有默认空字符串
        new_name = request.POST.get('new_name','').strip()
        # 设定输入不能为空
        if not new_name:
            return render(request,'add_publisher.html',{'err_msg':'输入不能为空','name':new_name})
        # 设定不能与数据库现有数据重复
        obj_list =  models.Publisher.objects.filter(name=new_name)    # 在数据库中查询数据是否存在
        if obj_list:        # 数据重复
            return render(request, 'add_publisher.html', {'err_msg': '出版社名称已存在', 'name': new_name})
        # orm往数据库中写入数据
        if new_name and not obj_list:
            models.Publisher.objects.create(name=new_name)
            return redirect('/publisher_list/')
    # 如果不是post请求,还是返回本页面
    return render(request,'add_publisher.html')
示例

CBV : class base views    在试图里使用类处理请求

# url对应关系:url(r'^add_publisher/', views.add_publisher.as_view()),
from django.views import View

class add_publisher(View):
    def get(self,request):
        '''get请求'''
        return render(request, 'add_publisher.html')
    def post(self,request):
        # 获取提交的数据(括号内为input的name属性值),没有默认空字符串
        new_name = request.POST.get('new_name', '').strip()
        # 设定输入不能为空
        if not new_name:
            return render(request, 'add_publisher.html', {'err_msg': '输入不能为空', 'name': new_name})
        # 设定不能与数据库现有数据重复
        obj_list = models.Publisher.objects.filter(name=new_name)  # 在数据库中查询数据是否存在
        if obj_list:  # 数据重复
            return render(request, 'add_publisher.html', {'err_msg': '出版社名称已存在', 'name': new_name})
        # orm往数据库中写入数据
        if new_name and not obj_list:
            models.Publisher.objects.create(name=new_name)
            return redirect('/publisher_list/')
示例

 as_view()流程

1.程序启动的时候,执行as_view() 定义view函数并返回return self.dispatch(request, *args, **kwargs)

  url(r'^add_publisher/', views.add_publisher.as_view()) 此时就相当于url(r'^add_publisher/', view)

2.接收到请求的时候,执行view函数

  1.实例化当前的类 将对象传给self

  2.self.request = request

  3.指定返回的self.dispatch方法:

    1.判断请求方式是否允许

      允许 ---- 通过反射拿到对应请求方式的方法 赋值给handler

      不允许 ---- 执行self.http_method_not_allowed 赋值给handler

    2.执行handler 得到HttpResponse对象 返回

 给视图加装饰器

FBV本身就是函数,和普通的函数加装饰器的方法一样,没有区别

给CBV加装饰器

from django.utils.decorators import method_decorator

#装饰器
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        ret = func(*args,**kwargs)
        print('时间:{}'.format(time.time() - start))
        return ret
    return inner


# 1.加在方法上

@method_decorator(timer)
def get(self,request):
    '''get请求'''
    return render(request, 'add_publisher.html')


# 2.加在dispatch方法上
@method_decorator(timer)
def dispatch(self, request, *args, **kwargs):     # 将源码中的dispatch方法重新定义,相当于给所有方法加上装饰器
    ret = super().dispatch(request, *args, **kwargs)
    return ret
    
    
# 3.加在类上
@method_decorator(timer,name='post')
@method_decorator(timer,name='get')       # 在name中指定要加装饰器的方法
class AddPublisher(View):
    def dispatch(self, request, *args, **kwargs):
        pass
    def get(self,request):
        pass
    def post(self,request):
        pass
    

@method_decorator(timer,name='dispatch')        # 或者直接指定dispatch方法,效果同方法2一样,给所有方法加上装饰器
    def dispatch(self, request, *args, **kwargs):
        pass
    def get(self,request):
        pass
    def post(self,request):
        pass
给CBV加装饰器

method_decorator使不使用对于代码的运行效果来说,没有什么不同

但是从参数角度来讲:

不使用method_decorator,打印args的结果:

  (<app01.views.AddPublisher object at 0x03B465B0>, <WSGIRequest: GET '/add_publisher/'>)

使用method_decorator,打印args的结果:

  (<WSGIRequest: GET '/add_publisher/'>,)

request

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

Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象

#  属性
request.method        # 请求方法
request.GET           # URL上携带的参数
request.POST          # POST请求提交的数据
request.FILES         # 上传的文件
request.path_info     # 路径   不包含IP 端口 参数
request.body          # 请求体   请求数据 字节  get没有请求体
request.META          # 请求头的信息  全部大写 HTTP_开头
request.COOKIES    
request.session

#  方法
request.get_full_path()    # 路径  不包含IP和端口 包含参数
request.is_ajax()          # 是否是ajax请求,布尔值
request.get_host()         # 获取主机的IP和端口

上传文件

1.from表单中规定编码方式 enctype="multipart/form-data"

2.使用request.FILES方法获取文件

3.写入文件: 文件名.chunks 将文件分块 循环写入

from django.shortcuts import render

def upload(request):
    if request.method == 'POST':
        file = request.FILES.get('file')        # request.FILES获取到字典,通过键取值
        with open(file.name,'wb') as f:         # file.name拿到文件名
            for chunk in file.chunks():
                f.write(chunk)
    return render(request,'upload.html')
# 文件会自动保存到与manage.py同一个路径下
函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}

    文件 <input type="file"  name="s19">
    <button>上传</button>
</form>
</body>
</html>
模板

response

HttpResponse('字符串') 返回字符串

render(request,'模板的文件名',{k1:v1}) 返回一个完整的HTML页面

redirect(要跳转的地址) 重定向 Location :地址

每个视图都需要实例化,填充和返回一个HttpResponse,render和redirect源码中都包含HttpResponse

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

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

from django.http.response import JsonResponse
def json_data(request):
    data = {'name':'alex','age':18}
    # lst = [1,2,3,4,5]
    return JsonResponse(data)
    # return JsonResponse(lst,safe=False)          # 传输非字典类型
示例
原文地址:https://www.cnblogs.com/sandy-123/p/10677753.html