目录

一.DRF中的Request

在Django REST Framework中内置的Request类扩展了Django中的Request类, 实现了很多方便的功能 -- 如请求数据解析和认证等.

比如, 区别于Django中的request: 从request.GET中获取URL参数, 从request.POST中去取某些情况下的POST数据(前端提交过来的数据).

在APIView中封装的request, 就实现了请求数据的解析:

  • 对于GET请求的参数, APIView通过request.query_params来获取
  • 对于POST请求、PUT请求的数据, APIView通过request.data来获取

二.前戏: 关于面向对象的继承

  1. # 讲一个葫芦娃的故事
  2. class Wa1(object):
  3. name = "红娃"
  4. def f1(self):
  5. print("力大无穷!")
  6. class Wa2(object):
  7. name = '橙娃'
  8. def f2(self):
  9. print('千里眼顺风耳!')
  10. class Wa3(object):
  11. name = '黄娃'
  12. def f3(self):
  13. print('钢筋铁骨!')
  14. class Wa4(object):
  15. name = '绿娃'
  16. def f4(self):
  17. print("会喷火!")
  18. class Wa5(object):
  19. name = '青蛙'
  20. def f5(self):
  21. print("会喷水!")
  22. class Jishuwa(Wa1, Wa3, Wa5):
  23. name = '奇数娃'
  24. def ff(self):
  25. print("我是{}, 我会:".format(self.name))
  26. self.f1()
  27. self.f3()
  28. self.f5()
  29. class Oushuwa(Wa2, Wa4):
  30. name = '偶数娃'
  31. def ff(self):
  32. print("我是{}, 我会:".format(self.name))
  33. self.f2()
  34. self.f4()
  35. jsw = Jishuwa()
  36. jsw.ff()
  37. osw = Oushuwa()
  38. osw.ff()
  39. # 直接定义一个基数娃
  40. class Taowa(Wa1, Wa3, Wa5):
  41. name = '套娃'
  42. def ff(self):
  43. print("我是{}, 我会:".format(self.name))
  44. self.f1()
  45. self.f3()
  46. self.f5()
  47. class Wawa(Taowa):
  48. pass
  49. print("=" * 120)
  50. a = Wawa()
  51. a.ff()

三.初级版本

1. settings.py文件 -- 注册app

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'bms.apps.BmsConfig',
  9. 'rest_framework', # 注册app
  10. ]

2. models.py文件 -- 创建表

  1. from django.db import models
  2. # 出版社表
  3. class Publisher(models.Model):
  4. name = models.CharField(max_length=32)
  5. def __str__(self):
  6. return self.name
  7. # 书籍表
  8. class Book(models.Model):
  9. title = models.CharField(max_length=32)
  10. publisher = models.ForeignKey(to='Publisher', to_field='id', on_delete=models.CASCADE)
  11. def __str__(self):
  12. return self.title
  1. # cd到当前项目目录
  2. # 执行数据库迁移指令
  3. python manage.py makemigrations
  4. python manage.py migrate

3. admin.py文件

  1. from django.contrib import admin
  2. from bms import models # bms是我们的app
  3. admin.site.register(models.Publisher)
  4. admin.site.register(models.Book)
  1. # 创建超级用户
  2. # cd到当前项目目录
  3. python manage.py createsuperuser
  1. # 启动Django项目
  2. python manage.py runserver 127.0.0.1:8000
  1. # 浏览器地址栏输入 127.0.0.1:8000
  2. # 输入账号和密码,进入admin页面,对数据库中的表 添加或修改相关数据

4. 根目录下urls.py -- 路由匹配

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from bms import views
  4. urlpatterns = [
  5. url(r'^admin/', admin.site.urls),
  6. url(r'^book/$', views.BookListView.as_view()),
  7. url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view()),
  8. ]

5. bms/views.py -- 视图函数

  1. from rest_framework.response import Response
  2. from rest_framework.views import APIView
  3. from bms import models
  4. from bms.modelserializers import BookModelSerializer
  5. class BookListView(APIView):
  6. def get(self, request):
  7. # 1.从数据库查询出所有书籍对象
  8. queryset = models.Book.objects.all()
  9. # 2.使用modelserializer对获取的对象进行序列化
  10. ser_obj = BookModelSerializer(queryset, many=True)
  11. return Response(ser_obj.data)
  12. def post(self, request):
  13. # 1.获取前端提交过来的数据 --> request.data
  14. # 2.对数据进行有效性校验
  15. ser_obj = BookModelSerializer(data=request.data)
  16. if ser_obj.is_valid():
  17. ser_obj.save()
  18. return Response('添加成功!')
  19. else:
  20. return Response(ser_obj.errors)
  21. class BookDetailView(APIView):
  22. def get(self, request, pk): # get获取具体某本书的信息
  23. # 1.根据pk去数据库中查询具体的那本书籍对象
  24. book_obj = models.Book.objects.filter(pk=pk).first()
  25. if book_obj:
  26. # 2.将书籍对象 序列化成 json格式的数据
  27. ser_obj = BookModelSerializer(book_obj)
  28. # 3.返回响应
  29. return Response(ser_obj.data)
  30. else:
  31. return Response('无效的书籍id')
  32. def put(self, request, pk): # put修改具体某本书的信息
  33. # 1.根据pk去查询具体的那本书籍对象
  34. book_obj = models.Book.objects.filter(pk=pk).first()
  35. if book_obj:
  36. # 2.获取用户发送过来的数据并修改数据
  37. ser_obj = BookModelSerializer(instance=book_obj, data=request.data, partial=True)
  38. if ser_obj.is_valid():
  39. # 3.保存并返回修改后的数据
  40. ser_obj.save()
  41. return Response(ser_obj.data)
  42. else:
  43. return Response(ser_obj.errors)
  44. else:
  45. return Response('无效的书籍id')
  46. def delete(self, request, pk): # delete删除具体某一本书籍对象
  47. # 1.根据pk去查询具体的那本书籍对象
  48. book_obj = models.Book.objects.filter(pk=pk).first()
  49. if book_obj:
  50. # 2.删除该书籍对象
  51. book_obj.delete()
  52. return Response('删除成功')
  53. else:
  54. return Response('无效的书籍id')

6. bms/modelserializers.py -- 自定义序列化工具

  1. from rest_framework import serializers
  2. from bms import models
  3. class PublisherSerializer(serializers.Serializer):
  4. id = serializers.IntegerField()
  5. name = serializers.CharField()
  6. class BookModelSerializer(serializers.ModelSerializer):
  7. publisher_info = serializers.SerializerMethodField(read_only=True)
  8. def get_publisher_info(self, book_obj):
  9. return PublisherSerializer(book_obj.publisher).data
  10. class Meta:
  11. model = models.Book
  12. fields = '__all__'
  13. extra_kwargs = {
  14. 'publisher': {'write_only': True},
  15. }
  16. class PublisherModelSerializer(serializers.ModelSerializer):
  17. class Meta:
  18. model = models.Publisher
  19. fields = '__all__'

四.进化版: 使用自定义混合类和自定义通用类

提取出views.py文件中函数BookListViewBookDetailView代码中的重复部分, 并将这些重复部分封装为通用类(Generic)混合类(Mixin), 利用Python强大的多继承功能, 将代码进一步优化. 充分体现Python语言的"优雅"和"简洁".

注意: 混合类Mixin不能单独实例化, 需要与其他的类搭配使用.

bms/views.py:

  1. from rest_framework.response import Response
  2. from rest_framework.views import APIView
  3. from bms import models
  4. from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
  5. # 通用功能
  6. class GenericView(APIView):
  7. queryset = None
  8. serializer_class = None
  9. def get_queryset(self, request, *args, **kwargs):
  10. # 再一次调用all()方法: 让每次请求来的时候都重新查一次数据
  11. return self.queryset.all()
  12. def get_obj(self, request, pk, *args, **kwargs):
  13. return self.get_queryset(request, *args, **kwargs).filter(pk=pk).first()
  14. # get展示(全部)资源
  15. class ListMixin(object):
  16. def get(self, request):
  17. queryset = self.get_queryset(request)
  18. ser_obj = self.serializer_class(queryset, many=True)
  19. return Response(ser_obj.data)
  20. # post添加资源
  21. class CreateMixin(object):
  22. def post(self, request):
  23. ser_obj = self.serializer_class(data=request.data)
  24. if ser_obj.is_valid():
  25. ser_obj.save()
  26. return Response('添加成功!')
  27. else:
  28. return Response(ser_obj.errors)
  29. # get展示(部分)资源
  30. class RetrieveMixin(object):
  31. def get(self, request, pk, *args, **kwargs):
  32. obj = self.get_obj(request, pk, *args, **kwargs)
  33. if obj:
  34. ser_obj = self.serializer_class(obj)
  35. return Response(ser_obj.data)
  36. else:
  37. return Response('无效的id!')
  38. # put更新(修改)资源
  39. class UpdateMixin(object):
  40. def put(self, request, pk, *args, **kwargs):
  41. obj = self.get_obj(request, pk, *args, **kwargs)
  42. if obj:
  43. ser_obj = self.serializer_class(instance=obj, data=request.data, partial=True)
  44. if ser_obj.is_valid():
  45. ser_obj.save()
  46. return Response(ser_obj.data)
  47. else:
  48. return Response(ser_obj.errors)
  49. else:
  50. return Response('无效的id!')
  51. # delete删除资源
  52. class DestroyMixin(object):
  53. def delete(self, request, pk, *args, **kwargs):
  54. obj = self.get_obj(request, pk, *args, **kwargs)
  55. if obj:
  56. obj.delete()
  57. return Response('删除成功!')
  58. else:
  59. return Response('无效的id!')
  60. class BookListView(GenericView, ListMixin, CreateMixin):
  61. queryset = models.Book.objects.all()
  62. serializer_class = BookModelSerializer
  63. class BookDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
  64. queryset = models.Book.objects.all()
  65. serializer_class = BookModelSerializer
  66. class PublisherListView(GenericView, ListMixin, CreateMixin):
  67. queryset = models.Publisher.objects.all()
  68. serializer_class = PublisherModelSerializer
  69. class PublisherDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
  70. queryset = models.Publisher.objects.all()
  71. serializer_class = PublisherModelSerializer

urls.py:

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from bms import views
  4. urlpatterns = [
  5. url(r'^admin/', admin.site.urls),
  6. url(r'^book/$', views.BookListView.as_view()),
  7. url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view()),
  8. url(r'^publisher/$', views.PublisherListView.as_view()),
  9. url(r'^publisher/(?P<pk>\d+)$', views.PublisherDetailView.as_view()),
  10. ]

五.超级进化版: 使用GenericViewSet通用类

GenericViewSetrest_framework这个app中已经封装好了的一个类:

  1. from rest_framework.viewsets import GenericViewSet

需要注意的是, 继承了GenericViewSet以后, GenericViewSet这个类已经帮我们封装好了get_queryset()get_object()这两个方法, 它们不需要接收参数, 我们直接调用即可.

bms/views.py:

  1. from rest_framework.response import Response
  2. from bms import models
  3. from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
  4. from rest_framework.viewsets import GenericViewSet # 引入GenericViewSet通用类
  5. # get展示(全部)资源
  6. class ListMixin(object):
  7. def list(self, request, *args, **kwargs):
  8. queryset = self.get_queryset()
  9. ser_obj = self.serializer_class(queryset, many=True)
  10. return Response(ser_obj.data)
  11. # post添加资源
  12. class CreateMixin(object):
  13. def create(self, request, *args, **kwargs):
  14. ser_obj = self.serializer_class(data=request.data)
  15. if ser_obj.is_valid():
  16. ser_obj.save()
  17. return Response('添加成功!')
  18. else:
  19. return Response(ser_obj.errors)
  20. # get展示(部分)资源
  21. class RetrieveMixin(object):
  22. def retrieve(self, request, pk, *args, **kwargs):
  23. obj = self.get_object()
  24. if obj:
  25. ser_obj = self.serializer_class(obj)
  26. return Response(ser_obj.data)
  27. else:
  28. return Response('无效的id!')
  29. # put更新(修改)资源
  30. class UpdateMixin(object):
  31. def update(self, request, pk, *args, **kwargs):
  32. obj = self.get_object()
  33. if obj:
  34. ser_obj = self.serializer_class(instance=obj, data=request.data, partial=True)
  35. if ser_obj.is_valid():
  36. ser_obj.save()
  37. return Response(ser_obj.data)
  38. else:
  39. return Response(ser_obj.errors)
  40. else:
  41. return Response('无效的id!')
  42. # delete删除资源
  43. class DestroyMixin(object):
  44. def destroy(self, request, pk, *args, **kwargs):
  45. obj = self.get_object()
  46. if obj:
  47. obj.delete()
  48. return Response('删除成功!')
  49. else:
  50. return Response('无效的id!')
  51. class BookViewSet(GenericViewSet, ListMixin, CreateMixin, RetrieveMixin, UpdateMixin, DestroyMixin):
  52. queryset = models.Book.objects.all()
  53. serializer_class = BookModelSerializer
  54. class PublisherViewSet(GenericViewSet, ListMixin, CreateMixin, RetrieveMixin, UpdateMixin, DestroyMixin):
  55. queryset = models.Publisher.objects.all()
  56. serializer_class = PublisherModelSerializer

urls.py:

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from bms import views
  4. urlpatterns = [
  5. url(r'^admin/', admin.site.urls),
  6. url(r'^book/$', views.BookViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
  7. url(r'^book/(?P<pk>\d+)$', views.BookViewSet.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
  8. url(r'^publisher/$', views.PublisherViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
  9. url(r'^publisher/(?P<pk>\d+)$', views.PublisherViewSet.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
  10. ]

六.究极进化版: 使用rest_framework帮我们封装好的通用类和混合类

bms/views.py:

  1. from bms import models
  2. from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
  3. from rest_framework.viewsets import ModelViewSet
  4. class BookViewSet(ModelViewSet):
  5. queryset = models.Book.objects.all()
  6. serializer_class = BookModelSerializer
  7. class PublisherViewSet(ModelViewSet):
  8. queryset = models.Publisher.objects.all()
  9. serializer_class = PublisherModelSerializer

七.终极进化版: 使用rest_framework帮我们封装好的路由DefaultRouter

  1. from rest_framework.routers import DefaultRouter
  2. from bms import views
  3. urlpatterns = []
  4. router = DefaultRouter()
  5. router.register('book', views.BookViewSet)
  6. router.register('publisher', views.PublisherViewSet)
  7. # 重写urlpatterns
  8. urlpatterns += router.urls

DRF 视图的更多相关文章

  1. 使用DRF视图集时自定义action方法

    在我们用DRF视图集完成了查找全部部门,创建一个新的部门,查找一个部门,修改一个部门,删除一个部门的功能后,views.py的代码是这样子的: class DepartmentViewSet(Mode ...

  2. 【DRF视图】

    目录 开始使用内置视图 请结合[DRF序列化]此文献中的数据文件及序列化文件来阅读如下代码. DRF视图为我们提供了非常简便的方法--内置了增删改查等一系列的操作. 我们只需在url中指定对应的方法, ...

  3. DRF视图-请求与响应

    DRF视图 drf的代码简写除了在数据序列化体现以外,在视图中也是可以的.它在django原有的django.views.View类基础上,drf内部封装了许多子类以便我们使用. Django RES ...

  4. DRF视图组件

    DRF视图组件: CVB模式继承----五层 from django.views import View # Django的View from rest_framework.views import ...

  5. drf 视图使用及源码分析

    前言 drf视图的源码非常的绕,但是实现的功能却非常的神奇. 它能够帮你快速的解决ORM增删改查的重复代码,非常的方便好用. 下面是它源码中的一句话: class ViewSetMixin: &quo ...

  6. DRF 视图组件

    目录 DRF 视图组件 视图组件大纲 两个视图基本类 五个扩展类 九个子类视图 视图集 常用视图集父类 魔法类 一览表 DRF中视图的"七十二变" 第一层:基于APIview的五个 ...

  7. restfull规范、DRF视图和路由

    一.restfull规范的简单介绍 1.介绍 REST:表述性状态转移,是一种web交互方案 资源:在web中只要有被引用的必要都是资源 URI: URI 统一资源标识符 URL 统一资源定位符 统一 ...

  8. drf视图组件、认证组件

    视图组件 1.基本视图 url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>\d+)/$', vi ...

  9. DRF 视图和路由

    Django Rest Feamework 视图和路由 DRF的视图 APIView 我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个 ...

  10. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

随机推荐

  1. MQTT协议学习及实践(Linux服务端,Android客户端的例子)

    前言 MQTT(Message Queuing Telemetry Transport),是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提 ...

  2. 【转载】使用Docker Hub官方gcc:latest镜像编译C/C++程序以及缩小镜像的方法

    摘要:使用Docker Hub官方gcc:latest镜像(1.2GB)编译C/C++程序,以及缩小镜像的方法. 方法1: 在gcc容器里编译C/C++程序 将C/C++代码运行在gcc容器内的最简单 ...

  3. Ajax请求小结

    参数说明 ajax请求异步刷新页面=把需要异步刷新的页面单独写成一个.cshtml进行操作$.ajax({}); -------ajax方法.type: ------- 类型,此处为“POST” 还有 ...

  4. linux C 内存管理方式之半动态

    看到半动态申请内存,第一反应这是什么鬼? 实际上半动态内存申请很容易理解,在GNU C中使用alloca函数来实现 #include <stdlib.h> void *alloca (si ...

  5. C#基于用户和角色的验证,服务端web 客户端wpf

    应用程序服务 <?xml version="1.0"?> <!--  For more information on how to configure your ...

  6. Android permission 动态申请、授权

    原文:Android permission 动态申请.授权 Android permission 新特性深度学习 本篇文章介绍android permission系统,并介绍android 6.0 p ...

  7. iOS NSString追加字符串的方法

    第一种: NSArray *array = [NSArray arrayWithObjects:@"Hello",@" ",@"world" ...

  8. Unpaired/Partially/Unsupervised Image Captioning

    这篇涉及到以下三篇论文: Unpaired Image Captioning by Language Pivoting (ECCV 2018) Show, Tell and Discriminate: ...

  9. Win10 UWP版《芒果TV》v2.4.0直播超女,芒果台综艺一网打尽

    Win10 UWP版<芒果TV>直播超女,芒果台综艺一网打尽 Win10版UWP<芒果TV>自2015年9月登录商店以来,一直在持续更新,积极改进,拥有芒果台视频的独家点播和直 ...

  10. Advanced Installer读取注册表时将Program Files读取为Program Files (x86)的解决办法

    原文:Advanced Installer读取注册表时将Program Files读取为Program Files (x86)的解决办法 今天同事在做安装包的时候,有一个读取注册表路径的需求,需要根据 ...