django(7)、视图Views

FBV

FBV(function base views) 就是在视图里使用 函数 处理请求。

  • 1、仅仅是一个函数,接收request作为参数,return响应的数据;
  • 2、返回的数据可以为html页面内容、redirect、404error、image,即任意可以用二进制描述的数据;
  • 3、函数内部包含任意逻辑,作用是取出并返回需要的响应数据;
  • 4、可以在python解释器能找到的任意路径,但惯例是放在app目录下的views.py文件中。

常用的方法

  • 1、render(request, 'index.html',{k:v,..}):从数据库中取出数据渲染到模板,再返回给浏览器展示,或者直接返回模板内容到浏览器.

  • 2、HttpResponse(str):返回固定字符串,若为标签文本,页面亦可以识别:

    def index(request):
        return HttpResponse('<h1>hello django</h1>')
  • 3、redirect('/login/'):重新到路由配置下逐条匹配url,再进入对应的视图,返回需要的数据。


CBV模型

CBV(class base views) 就是在视图里使用 处理请求。

  • url对应一个视图类、此类调用父类的dispatch()方法,会根据http请求头里的方法是get还是post方法来执行相应的函数。
  • 在触发视图类的时候可以在dispatch函数内部实现一些逻辑判断;

CBV源码分析

# step 1:配置路由===================================
url(r'^index/$',views.IndexView.as_view())


# step 2===================================
from django.views import View

class View(object):
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        pass
        
    @classonlymethod
    def as_view(cls, **initkwargs):
        # 一般没有传递参数,initkwargs 为 None
        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__))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            # step 3: 调用dispatch方法===================================
            return self.dispatch(request, *args, **kwargs)
            
        view.view_class = cls
        view.view_initkwargs = initkwargs
        return view

    def dispatch(self, request, *args, **kwargs):
        # step 4: 查看请求的方法是否在设定的方法列表中===================
        if request.method.lower() in self.http_method_names:
            # step 5: 获取方法===================
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        # step 6: 调用方法===================
        return handler(request, *args, **kwargs)

自定制dispatch函数

from django.views import View
from django.shortcuts import render, redirect,HttpResponse


class LoginView(View):
    def dispatch(self, request, *args, **kwargs):
        '''可以在内部做出逻辑判断'''
        if request.POST.get('username')=='alex':
            return HttpResponse('用户名已注册')
        ret = super(LoginView, self).dispatch(request, *args, **kwargs)
        return ret

    def get(self, request):
        obj = MyForm()
        return render(request, 'login.html', {'form': obj})

    def post(self, request):
        obj = MyForm(request.POST, request.FILES)
        errors = {}
        if obj.is_valid():
            values = obj.clean()
            print(values)
        else:
            errors = obj.errors
            print(errors)
        return render(request, 'login.html', {'form': obj, 'errors': errors})
  • 弊端:每个视图类内部都需要定义dispatch函数,造成重复代码。
  • 改进:自定制view类,用来继承即可:

    from django.views import View
    from django.shortcuts import render, redirect, HttpResponse
    from .forms import LoginForm
    
    
    class MyView(View):
        def dispatch(self, request, *args, **kwargs):
            """可以在内部做出逻辑判断"""
            if request.POST.get('username') == 'alex':
                return HttpResponse('用户名已注册')
            ret = super(MyView, self).dispatch(request, *args, **kwargs)
            return ret
    
    
    class LoginView(MyView, View):
        def get(self, request):
            obj = LoginForm()
            return render(request, 'login.html', locals())
    
        def post(self, request):
            obj = LoginForm(request.POST, request.FILES)
            errors = {}
            if obj.is_valid():
                values = obj.clean()
                print(values)
            else:
                errors = obj.errors
                print(errors)
            return render(request, 'login.html', locals())

猜你喜欢

转载自www.cnblogs.com/fqh202/p/9442276.html