django视图层

视图层

views.py

JsonResponse

前后端分离的情况下,通常采用json文件进行交互.

通常使用字典+开发文档的形式交互.

JsonResponse对象是HttpResponse对象的子类.

前后端序列化对比

Python JavaScript
json.dumps JSON.stringify
json.loads JSON.parse
def index(request):
    user_dic = {'name':'jason好帅哦 我好喜欢~','password':'123'}
    # 让json不自动帮你对中文进行转码  ensure_ascii参数
    # json_str = json.dumps(user_dic,ensure_ascii=False)
    # return HttpResponse(json_str)
    # return JsonResponse(user_dic,json_dumps_params={'ensure_ascii':False})
    l = [1,2,3,4,5,6,7,]
    # JsonResponse默认是序列化字典用的 如果你想序列化其他数据类型(json模块能够序列化的) 你需要加一个safe参数
    return JsonResponse(l,safe=False)

FBV(function bases views)

基于函数的视图

# 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(class bases views)

基于类的视图

# 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()),

CBV源码流程

#utls.py中开始
urlpatterns = [
    url(r'^login/',views.MyLogin.as_view()),
]
#调用login后,去views的MyLogin找as_view()方法
#views.py
class MyLogin(View):
    
    def get(self,request):
        print('我是MyLogin里面的get方法')
        return render(request,'login.html')

    def post(self,request):
        print('我是MyLogin里面的post方法')
        return HttpResponse('post')
'''
1.没有找到,再去MyLogin的父类View中找as_view()找
2.在as_view中找到类方法,其返回值为view,
3.在view中将request,args,kwargs赋值,并调用dispatch函数
4.在dispathch中,通过反射getattr得到request.method方法并返回
5.回到views.py中在MyLogin中调用对应函数
'''
#base.py
@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)
                    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)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)   
总结

1.调用login后,去views的MyLogin找as_view()方法
2.没有找到,再去MyLogin的父类View中找as_view()找
3.在as_view中找到类方法,其返回值为view,
4.找到as_view内层函数view
5.在view中将request,args,kwargs赋值,并调用dispatch函数
6.在dispathch中,通过反射getattr得到request.method方法并返回
7.handler为1/8methde_names,并传入对应函数调用
8.回到views.py中执行对应函数

CBV装饰器

使用内置装饰器

#装饰器
def outter(func):
    @wraps(func)
    def inner(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time() - start_time
        print('函数执行时间:%s'%end_time)
        return res
    return inner

from django.utils.decorators import method_decorator
# 2.可以指定给谁装
# @method_decorator(outter,name='post')
# @method_decorator(outter,name='dispatch')
class MyLogin(View):
    @method_decorator(outter)
    def dispatch(self, request, *args, **kwargs):  # 覆盖父类dispathch方法来是实现
        return super().dispatch(request,*args,**kwargs)
    # @outter  # 1.直接写
    # @method_decorator(outter)  # 1.推荐写法
    def get(self,request):
        print('我是MyLogin里面的get方法')
        return render(request,'login.html')
    # @outter
    def post(self,request):
        print('我是MyLogin里面的post方法')
        time.sleep(1)
        return HttpResponse('post')
posted @ 2019-11-26 20:14  Agsol  阅读(80)  评论(0编辑  收藏  举报