zoukankan      html  css  js  c++  java
  • CBV&FBV

    CBV和FBV

    我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类的。

    就拿我们之前写过的添加班级为例:

    FBV版:

    复制代码
    # FBV版添加班级
    def add_class(request):
        if request.method == "POST":
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")
        return render(request, "add_class.html")
    复制代码

    CBV版:

    复制代码
    # CBV版添加班级
    from django.views import View
    
    
    class AddClass(View):
    
        def get(self, request):
            return render(request, "add_class.html")
    
        def post(self, request):
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")
    复制代码

    注意:

    使用CBV时,urls.py中也做对应的修改:

    # urls.py中
    url(r'^add_class/$', views.AddClass.as_view()),
    

      

    给视图加装饰器

    使用装饰器装饰FBV

    FBV本身就是一个函数,所以和给普通的函数加装饰器无差:

    复制代码
    def wrapper(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            ret = func(*args, **kwargs)
            end_time = time.time()
            print("used:", end_time-start_time)
            return ret
        return inner
    
    
    # FBV版添加班级
    @wrapper
    def add_class(request):
        if request.method == "POST":
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")
        return render(request, "add_class.html")

    使用装饰器装饰CBV

    类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。

    Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。

    复制代码
    # CBV版添加班级
    from django.views import View
    from django.utils.decorators import method_decorator
    
    class AddClass(View):
    
        @method_decorator(wrapper)
        def get(self, request):
            return render(request, "add_class.html")
    
        def post(self, request):
            class_name = request.POST.get("class_name")
            models.Classes.objects.create(name=class_name)
            return redirect("/class_list/")
    复制代码

    上传文件示例

    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")
    

      

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

    request.POST.getlist("hobby")

    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")

    设置或删除响应头信息

    response = HttpResponse()
    response['Content-Type'] = 'text/html; charset=UTF-8'
    del response['Content-Type']

    属性

    HttpResponse.content:响应内容

    HttpResponse.charset:响应内容的编码

    HttpResponse.status_code:响应的状态码

    JsonResponse对象

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

    from django.http import JsonResponse
    
    response = JsonResponse({'foo': 'bar'})
    print(response.content)
    
    b'{"foo": "bar"}'

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

    response = JsonResponse([1, 2, 3], safe=False)

    render()

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

    参数:
         request: 用于生成响应的请求对象。
    
         template_name:要使用的模板的完整名称,可选的参数
    
         context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
    
         content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'
    
         status:响应的状态码。默认为200。

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

    一个简单的例子:
    from django.shortcuts import render
    
    def my_view(request):
        # 视图的代码写在这里
        return render(request, 'myapp/index.html', {'foo': 'bar'})

    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)  

    扩展阅读: 

    临时重定向(响应状态码:302)和永久重定向(响应状态码:301)对普通用户来说是没什么区别的,它主要面向的是搜索引擎的机器人。

    A页面临时重定向到B页面,那搜索引擎收录的就是A页面。

    A页面永久重定向到B页面,那搜索引擎收录的就是B页面。

     
  • 相关阅读:
    Asp.net2.0页面执行顺序
    [转帖]常用的SQL语句
    [转帖]黑客技术经典问题FAQ
    面试的一些心得
    较全的正则表达式
    很好的创业建议
    [转帖]如何让菜单项与工具栏按钮对应
    源码下载网站
    [转帖]一段测试代码
    GOF设计模式趣解(23种设计模式) <转自百度空间>
  • 原文地址:https://www.cnblogs.com/ighuahua/p/10919286.html
Copyright © 2011-2022 走看看