zoukankan      html  css  js  c++  java
  • S11 day 94 RestFramework 之 APIView视图

    VIEW视图(Django自带的)

    1.  url 

        url(r'login/$', views.login.as_view()),

    2.点开 as_view() , as_view()为类方法.  login类里面没有as_view方法,所以会到继承的View类中去找as_view方法.

    from django.views import View
    class login(View):
    
        def get(self,request):
            return HttpResponse("get请求")
        def psot(self,request):
            return HttpResponse("post请求")

    3.   views.login.as_view() 等同于执行as_view方法。

      web请求后一定会有一个函数方法的返回return 那么 ,我们看到下面as_view 方法里面 定义了view方法,整个as_view函数返回的就是view 

      相当于:

        url(r'login/$', views.login.as_view()),

        ==> url(r'login/$', view),  执行view   ,一但用户访问login,执行的view(request,*args,**kwargs)

        ==>url(r'login/$', view),  执行view    一但用户方法login,执行的是 return self.dispatch(request, *args, **kwargs)

                                                 self.dispatch()

     

      最后执行dispatch方法 ,然后再看self 是谁的实例对象 ,这个self是谁取决于cls是谁( self = cls(**initkwargs) ) ===>def as_view(cls, **initkwargs): ,  login 类调用的as_view ,所以 这个self实例对象为login类的self , 那么我们就去login类里去找dispatch  ,发现login里面我们并没有定义dispatch, 我们就去View基类里去找dispatch  ,下面的dispatch 源码就是View基类里的源码dispatch方法。下面就来看dispatch里的执行顺序

     

    ,这个self为login 的类

    as_view 源码

     @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

    dispatch方法里面 有个getattr 方法 ,handler 就是执行login类里的譬如get方法。   

    dispatch执行的结果就是handler的执行结果.

    handler的执行就是self.get方法 

    dispatch源码 

        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)

    APIVIEW视图(restframework带的)

    1. 设置二级路由.

    url 路由 

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import app01_url   #导入二级路由文件
    
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^api/', include(app01_url)),
    
        #评论.
        # url(r'^comment_list/', views.comment),
        # url(r'^add_comment/', views.article_list),
        # url(r'^delete_comment/', views.article_list),
    ]

    二级路由  (在app目录下创建二级路由文件)

    from django.conf.urls import url
    from app01 import  views
    
    
    urlpatterns = [
        url(r'^article/', views.index),
        # url(r'article/(?P<pk>d+)', views.ArticleDetail.as_view(), name='article-detail'),
        # url(r'school/(?P<id>d+)', views.SchoolDetail.as_view(), name='school-detail111'),
    
    ]

    访问方法 :  http://127.0.0.1:8001/api/article/

    序列化 文件

    from app01.models import Comment,Article,School
    from rest_framework import serializers
    
    # 序列化评论类
    class CommentSerializer(serializers.ModelSerializer):
        class Meta:
            model = Comment
            fields ="__all__"
            # depth =1
    
    #序列化文章类
    class ArticleModelSerializer(serializers.ModelSerializer):
        class Meta:
            model =Article
            fields ="__all__"
    
    # 学校的序列化
    class SchoolSerializer(serializers.ModelSerializer):
        class Meta:
            model =School
            fields ="__all__"

      2. 序列化+APIVIEW视图

       A.GET请求

    from rest_framework.views import APIView
    from app01 import serializers as app01_serializer
    from rest_framework.views import Response
    class Comment(APIView):
        def get(self,request):
            res={"code":0}
            #数据
            all_comment =models.Comment.objects.all()
            #序列化
            ser_obj =app01_serializer.CommentSerializer(all_comment,many=True)
            print('ser_obj-->:',ser_obj)
            res["data"] =ser_obj.data
            return Response(res)

     打印结果:

       B.POST请求

        def post(self,request):
            res ={"code":0}
            #去提交的数据
            comment_data = self.request.data
            print("comment-data---------->",comment_data)
            #对用户提交的数据做校验
            ser_obj =app01_serializer.CommentSerializer(data=comment_data)
            if ser_obj.is_valid():
                # 表示数据没有问题,可以创建
                ser_obj.save()
                print('数据确认ok')
            else:
                #表示数据有问题
                res["code"] =1
                res["error"] =ser_obj.errors
                print('数据有问题')
            return Response(res)

    打印结果:

     3. 更改报错信息.

    # 序列化评论类
    class CommentSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Comment
            fields ="__all__"
            depth =1
            #定义额外的参数.
            extra_kwargs={
                "content":{
                    "error_messages":{
                       "required":"内容不能为空."
                    }
                }
            }

    结果:

     4 .校验钩子 Validation

    #用于做校验的钩子函数,类似于form组件的clean字段.
        #局部钩子
        def validate_content(self,value):
            if "fuck"  in value:
                raise ValidationError("不符合社会主义核心价值观")
            else:
                return value
    
    ==========以下代码没用上.
    
        #全局钩子
        def validate(self, attrs):
            self.validated_data # 经过校验的数据,类似于form组件里的cleaned_data
            pass

    结果:

     

     

     

    在restframework 中 POST请求封装在 request.data里 ,request.data提供多种解析器  ,传json数据可以解析 ,urenccoded数据可以解析

  • 相关阅读:
    Object.Instantiate 实例
    .idata数据的解析
    数据结构-静态链表
    数据结构-循环链表
    Android---两个视图间的淡入淡出
    HDU 4597 Play Game 2013 ACM-ICPC吉林通化全国邀请赛H题
    Android 编译时出现r cannot be resolved to a variable
    找工作笔试面试那些事儿(5)---构造函数、析构函数和赋值函数
    SFINAE 模板替换失败而非报错的应用
    模板实参推导 & xx_cast的实现
  • 原文地址:https://www.cnblogs.com/mengbin0546/p/9401762.html
Copyright © 2011-2022 走看看