20-Django之CBV、序列化、Form表单

一、FBV & CBV

CBV定义

Djanggo中的请求处理方式
FBV: Function Based View
/index/ func(request)

CBV: Class Based View
/index/ class(object)--get方法/post方法

View方法

  • View方法支持的http请求:
    ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
  • form表单提交请求:
    'get', 'post'
  • ajax提交请求:
    ['get'获取, 'post'发送, 'put'增加, 'patch'增加, 'delete'删除, 'head', 'options', 'trace']
  • 请求数据:用url去路由系统中找到对应的类/函数
    • 函数:直接执行函数
    • 类:类名()执行构造方法初始化-->执行类中的dispatch()方法-->dispatch()中拿到请求的method进行反射

dispatch方法

class A:
    def f1(self):
        self.f2()

class B(A):
    def f2(self):
        print("-->a.f2")
#关键点:找到self到底是谁,就从哪个self这个类开始找,没有就往上找
obj = B()
obj.f1()

#报错:A类中没有f2()方法
obj = A()
obj.f1()
========================
class View:
        def dispatch(self):
            func = getattr(self,'get')
            return func(...)

        def get()
            print(1)
    
class LoginView(View):
        def dispatch(self,request, *args, **kwargs):
            # 可以在执行dispatch方法前后统一执行一些代码,起到装饰器的作用
                print("before")
                response = super(LoginView, self).dispatch(request, *args, **kwargs)
                print("after")
            return response
        
        def get():
            print(2)
#打印结果为2
obj = LoginView()
obj.dispatch()

对于super(B, self).dispatch()可以这样理解:super(B, self)首先找到B的父类(就是类A),然后把类B的对象self转换为类A的对象,然后“被转换”的类A对象,先调用类B中的方法,如果没有,就向上调用类A中的方法。

应用场景:登录验证

  • 继承
    • 单继承
    • 多继承
  • 装饰器:@method_decorator(auth, name='post')
    #单继承方式
    class BaseView(View):
        def dispatch(self, request, *args, **kwargs):
            if request.session.get('username'):
                response = super(BaseView,self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')

    class IndexView(BaseView):
        def get(self, request, *args, **kwargs):
            return HttpResponse('Welcome! '+request.session.get('username'))

    #多继承方式
    class BaseView(object):
        def dispatch(self, request, *args, **kwargs):
            if request.session.get('username'):
                response = super(BaseView,self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
    
    class IndexView(BaseView, View):
        def get(self, request, *args, **kwargs):
            return HttpResponse('Welcome! '+request.session.get('username'))
    
    #装饰器
    from django.utils.decorators import method_decorator

    def auth(func):
        def inner(request, *args, **kwargs):
            if request.session.get('username'):
                obj = func(request, *args, **kwargs)
                return obj
            else:
                return redirect('/login.html')
        return inner
    
    @method_decorator(auth,name='get')
    class IndexView(View):
        # @method_decorator(auth)
        def get(self, request, *args, **kwargs):
            return HttpResponse('Welcome! ' + request.session.get('username'))

CBV中csrf的一个小bug

@method_decorator(csrf_exempt/protect)放在类或者对应方法上面时,不起作用,目前只能放在dispatch方法上面(对该类下的所有方法起作用)

from django.views.decorators.csrf import csrf_protect, csrf_exempt
from django.utils.decorators import method_decorator
class LoginView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        response = super(LoginView, self).dispatch(request, *args, **kwargs)
        return response

    def get(self, request, *args, **kwargs):    
        return render(request, 'login.html')

    def post(self, request, *args, **kwargs):
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'amy' and pwd == '123':
            request.session['username']=user
            return redirect('/index.html')
        return render(request, 'login.html', {'msg':'输入错误,请重新输入!'})

二、序列化

后端向前端传送数据

传统方式

def users(request):
    user_list = models.UserInfo.objects.all()
    return render(request, 'users.html', {'user_list':user_list})

方式1:序列化

serializers.serialize(),不推荐使用(数据过多)
def users(request):
return render(request, 'users.html')

from django.core import serializers
def get_users(request):
    user_list = models.UserInfo.objects.all()
    data = serializers.serialize('json',user_list) #将queryset格式转化为json
    return HttpResponse(data)

方式2:json.dumps()

def get_users(request):
    user_list = models.UserInfo.objects.values()
    user_list = list(user_list)
    data = json.dumps(user_list)
    return HttpResponse(data)

问题:对json.dumps做定制化

json.dumps()的局限性:只能处理python的数据类型,而对于date/datetime等类型就会报错
解决办法:

前提:取数据时用values()或者values_list(),保证取到的数据是json认识的类型

from django.test import TestCase
import json
from datetime import date
from datetime import datetime

class JsonCustomEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime):
            return o.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(o, date):
            return o.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, o)

user_list = [
    {'id':1,'user':'amy','ctime':datetime.now()},
    {'id':1,'user':'bulk','ctime':datetime.now()},
]

data = json.dumps(user_list,cls=JsonCustomEncoder)

前端展示


你可能感兴趣的:(20-Django之CBV、序列化、Form表单)