• 初识DRF


    第一部分 问题

    1. 前后端分离?

      • vue.js
      • 后端给前段返回json数据
    2. 移动端盛行。

      • app
      • 后端给app返回json数据
    3. PC端应用?

      crm项目,前段后端一起写,运行在浏览器上。 一般情况下都是PC端使用。 
      

    第二部分 任务

    以前的写的url :

    http://127.0.0.1:8000/info/get/
    http://127.0.0.1:8000/info/add/
    http://127.0.0.1:8000/info/update/
    http://127.0.0.1:8000/info/delete/
    

    现在的我们:要遵循restful规范

    http://127.0.0.1:8000/info/
    	get,获取数据
    	post,添加
    	put,更新
    	delete,删除
    

    基于django可以实现遵循restful规范的接口开发:

    • FBV,可以实现比较麻烦。
    • CBV,相比较简答根据method做的了不同的区分。

    第三部分 初识drf

    3.1 安装

    pip3 install djangorestframework
    

    3.2 使用

    • 注册app

      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          'rest_framework'
      ]
      
    • 写路由

      from django.conf.urls import url
      from django.contrib import admin
      from api import views
      
      urlpatterns = [
          url(r'^drf/info/', views.DrfInfoView.as_view()),
      ]
      
      
    • 写视图

      from rest_framework.views import APIView
      from rest_framework.response import Response
      
      class DrfInfoView(APIView):
      
          def get(self,request,*args,**kwargs):
              data = [
                  {'id': 1, 'title': '震惊了...王阳居然...', 'content': '...'},
                  {'id': 2, 'title': '震惊了...王阳居然...', 'content': '...'},
                  {'id': 3, 'title': '震惊了...王阳居然...', 'content': '...'},
                  {'id': 4, 'title': '震惊了...王阳居然...', 'content': '...'},
              ]
              return Response(data)
      

    DRF的应用场景

    以后在公司参与前后端分离项目、参与为app写接口时,用drf会比较方便。
    

    总结

    • restful规范

      1.给别人提供一个URL,根据URL请求方式的不同,做不同操作。
      	get,获取
      	post,增加
      	put,全部更新
      	patch,局部更新
      	delete,删除
      2.数据传输基于json格式。
      
    • drf框架

      不基于drf也可以实现restful规范来开发接口程序。
      
      使用了drf之后,可以快速帮我们开发restful规范来开发接口。
      

    第四部分

    4.1 创建程序并初始化数据库

    4.2 接口:实现访问接口时,创建一个文章类型

    from django.conf.urls import url
    from django.contrib import admin
    from api import views
    urlpatterns = [
        url(r'^drf/category/', views.DrfCategoryView.as_view()),
    ]
    
    
    from rest_framework.views import APIView
    from rest_framework.response import Response
    class DrfCategoryView(APIView):
    	pass
    

    假设:我是前段,你是后端。

    开发完毕之后告诉前端:

    http://127.0.0.1:8000/drf/category/
    

    用工具模拟前端发请求:postman

    请求方式:

    x-www-urlencoded

    request.body: name=alex&age=19&gender=12
    request.POST: {'name': ['alex'], 'age': ['19'], 'gender': ['12']}
    

    application/json

    request.body: b'{"ID":1,"name":"Alex","age":19}'
    request.POST: 没有值
    

    参考答案

    from django.conf.urls import url
    from django.contrib import admin
    from api import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^info/', views.InfoView.as_view()),
        url(r'^drf/info/', views.DrfInfoView.as_view()),
        url(r'^drf/category/', views.DrfCategoryView.as_view()),
    ]
    
    
    from api import models
    class DrfCategoryView(APIView):
    
        def post(self,request,*args,**kwargs):
            """增加一条分类信息"""
            models.Category.objects.create(**request.data)
            return Response('成功')
    
    

    4.3 接口:获取所有文章类型

    from api import models
    class DrfCategoryView(APIView):
        def get(self,request,*args,**kwargs):
            """获取所有文章分类"""
            queryset = models.Category.objects.all().values('id','name')
            data_list = list(queryset)
            return Response(data_list)
    
        def post(self,request,*args,**kwargs):
            """增加一条分类信息"""
            models.Category.objects.create(**request.data)
            return Response('成功')
    

    4.4 接口:获取一条文章类型的详细信息

    from django.conf.urls import url
    from django.contrib import admin
    from api import views
    urlpatterns = [
        url(r'^drf/category/$', views.DrfCategoryView.as_view()),
        url(r'^drf/category/(?P<pk>d+)/$', views.DrfCategoryView.as_view()),
    ]
    
    
    from api import models
    from django.forms.models import model_to_dict
    class DrfCategoryView(APIView):
        def get(self,request,*args,**kwargs):
            """获取所有文章分类/单个文章分类"""
            pk = kwargs.get('pk')
            if not pk:
                queryset = models.Category.objects.all().values('id','name')
                data_list = list(queryset)
                return Response(data_list)
            else:
                category_object = models.Category.objects.filter(id=pk).first()
                data = model_to_dict(category_object)
                return Response(data)
    
        def post(self,request,*args,**kwargs):
            """增加一条分类信息"""
            models.Category.objects.create(**request.data)
            return Response('成功')
    
    

    4.5 接口:文章分类的更新和删除

    from django.conf.urls import url
    from django.contrib import admin
    from api import views
    urlpatterns = [
        url(r'^drf/category/$', views.DrfCategoryView.as_view()),
        url(r'^drf/category/(?P<pk>d+)/$', views.DrfCategoryView.as_view()),
    ]
    
    
    from api import models
    from django.forms.models import model_to_dict
    class DrfCategoryView(APIView):
        def get(self,request,*args,**kwargs):
            """获取所有文章分类/单个文章分类"""
            pk = kwargs.get('pk')
            if not pk:
                queryset = models.Category.objects.all().values('id','name')
                data_list = list(queryset)
                return Response(data_list)
            else:
                category_object = models.Category.objects.filter(id=pk).first()
                data = model_to_dict(category_object)
                return Response(data)
    
        def post(self,request,*args,**kwargs):
            """增加一条分类信息"""
            models.Category.objects.create(**request.data)
            return Response('成功')
    
        def delete(self,request,*args,**kwargs):
            """删除"""
            pk = kwargs.get('pk')
            models.Category.objects.filter(id=pk).delete()
            return Response('删除成功')
    
        def put(self,request,*args,**kwargs):
            """更新"""
            pk = kwargs.get('pk')
            models.Category.objects.filter(id=pk).update(**request.data)
            return Response('更新成功')
    

    第五部分 drf的序列化

    drf的 serializers帮助我们提供了

    • 数据校验
    • 序列化
    from django.conf.urls import url
    from django.contrib import admin
    from api import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^info/$', views.InfoView.as_view()),
        url(r'^drf/info/$', views.DrfInfoView.as_view()),
        url(r'^drf/category/$', views.DrfCategoryView.as_view()),
        url(r'^drf/category/(?P<pk>d+)/$', views.DrfCategoryView.as_view()),
    
    
        url(r'^new/category/$', views.NewCategoryView.as_view()),
        url(r'^new/category/(?P<pk>d+)/$', views.NewCategoryView.as_view()),
    ]
    
    
    from rest_framework import serializers
    
    class NewCategorySerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Category
            # fields = "__all__"
            fields = ['id','name']
    
    class NewCategoryView(APIView):
        def get(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            if not pk:
                queryset = models.Category.objects.all()
                ser = NewCategorySerializer(instance=queryset,many=True)
                return Response(ser.data)
            else:
                model_object = models.Category.objects.filter(id=pk).first()
                ser = NewCategorySerializer(instance=model_object, many=False)
                return Response(ser.data)
    
        def post(self,request,*args,**kwargs):
            ser = NewCategorySerializer(data=request.data)
            if ser.is_valid():
                ser.save()
                return Response(ser.data)
            return Response(ser.errors)
    
        def put(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            category_object = models.Category.objects.filter(id=pk).first()
            ser = NewCategorySerializer(instance=category_object,data=request.data)
            if ser.is_valid():
                ser.save()
                return Response(ser.data)
            return Response(ser.errors)
    
        def delete(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            models.Category.objects.filter(id=pk).delete()
            return Response('删除成功')
    
    • 序列化的扩展
    from rest_framework import serializers
    
    class NewCategorySerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Category
            # fields = "__all__"
            # fields = ['id','name']
            # depth = 1
    
    fields中可以选择返回的数据,其它的就不会返回给前端了
    另外也可以在返回之前对这些数据进行操作
    例子:
    class NewCategorySerializer(serializers.ModelSerializer):
        category_txt = serializers.CharField(source='category.name',required=False)
        x1 = serializers.SerializerMethodField()
        class Meta:
            model = models.Category
            # fields = "__all__"
            fields = ['id','name','category_txt','x1']
        def get_x1(self,obj):
            return obj.category.name
    
    我在这个类中写上category_txt这个操作是什么意思?
    source将Category中的category这个属性(是一个外键)拿出来进行多表链接,查找它的名字,并且把category_txt放到fields中,那么返回前端的数据中就有这个值。
    
    requeired=False,这个意思是,当我对Category这个表进行增删改查时,不用给category_txt传值,因为他是不属于Category表例的属性。如果True的话,就会报错。
    
    serializers.CharField这个功能可以帮我们对这些数据进行再次操作
    
    
    我在这个类中写上x1这个操作是什么意思?
    这也是帮我们对这些数据进行再次操作的功能。
    定义钩子方法:
     def get_x1(self,obj):
            return obj.category.name
    obj是被序列化的类对象,return 返回给x1,并把x1写入fields中,一起返回给前端
    
    
    我在这个class Meta中写上depth这个操作是什么意思?
    一般fields=__all__使用,当Category表中有外键,一对一,一多对,多对多时,depth会自动帮我们拿到另一张表的所有数据,根据depth数值来决定。
    	假设:
        	depth = 1
            那么他只会跨一层表拿数据。
            depth = 2
            他会跨两层表拿数据。
    
    

    总结

    1. 什么是前后端分离?

      • 前端只写前端的代码
      • 后端只写后端的代码
      • 前端的数据通过接口发送请求,后端在返回给前端
    2. drf组件

      drf是一个基于django开发的组件,本质是一个django的app。 
      drf可以办我们快速开发出一个遵循restful规范的程序。
      
    3. drf如何帮助我们快速开发的?drf提供了那些功能?

      • 解析器,根据用户请求体格式不同进行数据解析,解析之后放在request.data中。
        在进行解析时候,drf会读取http请求头 content-type.
        如果content-type:x-www-urlencoded,那么drf会根据 & 符号分割的形式去处理请 求体。 user=wang&age=19
        如果content-type:application/json,那么drf会根据 json 形式去处理请求体。 {"user":"wang","age":19}
      • 序列化,对对象或对象列表(queryset)进行序列化操作以及表单验证的功能。
      • 视图,继承APIView(在内部apiview继承了django的View)
      • 渲染器,可以帮我们把json数据渲染到页面上进行友好的展示。(内部会根据请求设备不同做不同的 展示)
    4. postman

      模拟浏览器进行发送请求
      
    5. 查找模板的顺序

      优先根目录下:templates
      根据app的注册顺序去每个app的templates目录中找。
      
    6. 在URL的最后添加终止符

  • 相关阅读:
    Java new关键字的对象内存分配原理
    Android idleHandler
    Android Perffto工具
    Android Systrace工具
    Android TraceView工具
    Android App启动时间测量
    Android App启动分类
    Android线程的消息队列
    2018.2.28(延迟加载和缓存)
    2018.2.27(关联查询)
  • 原文地址:https://www.cnblogs.com/zhuzhizheng/p/11917670.html
Copyright © 2020-2023  润新知