一.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来获取

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

# 讲一个葫芦娃的故事

class Wa1(object):
name = "红娃" def f1(self):
print("力大无穷!") class Wa2(object):
name = '橙娃' def f2(self):
print('千里眼顺风耳!') class Wa3(object):
name = '黄娃' def f3(self):
print('钢筋铁骨!') class Wa4(object):
name = '绿娃' def f4(self):
print("会喷火!") class Wa5(object):
name = '青蛙' def f5(self):
print("会喷水!") class Jishuwa(Wa1, Wa3, Wa5):
name = '奇数娃' def ff(self):
print("我是{}, 我会:".format(self.name))
self.f1()
self.f3()
self.f5() class Oushuwa(Wa2, Wa4):
name = '偶数娃' def ff(self):
print("我是{}, 我会:".format(self.name))
self.f2()
self.f4() jsw = Jishuwa()
jsw.ff()
osw = Oushuwa()
osw.ff() # 直接定义一个基数娃
class Taowa(Wa1, Wa3, Wa5):
name = '套娃' def ff(self):
print("我是{}, 我会:".format(self.name))
self.f1()
self.f3()
self.f5() class Wawa(Taowa):
pass print("=" * 120)
a = Wawa()
a.ff()

三.初级版本

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

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bms.apps.BmsConfig',
'rest_framework', # 注册app
]

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

from django.db import models

# 出版社表
class Publisher(models.Model):
name = models.CharField(max_length=32) def __str__(self):
return self.name # 书籍表
class Book(models.Model):
title = models.CharField(max_length=32)
publisher = models.ForeignKey(to='Publisher', to_field='id', on_delete=models.CASCADE) def __str__(self):
return self.title
# cd到当前项目目录
# 执行数据库迁移指令
python manage.py makemigrations
python manage.py migrate

3. admin.py文件

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

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

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

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

from rest_framework.response import Response
from rest_framework.views import APIView
from bms import models
from bms.modelserializers import BookModelSerializer class BookListView(APIView):
def get(self, request):
# 1.从数据库查询出所有书籍对象
queryset = models.Book.objects.all()
# 2.使用modelserializer对获取的对象进行序列化
ser_obj = BookModelSerializer(queryset, many=True)
return Response(ser_obj.data) def post(self, request):
# 1.获取前端提交过来的数据 --> request.data
# 2.对数据进行有效性校验
ser_obj = BookModelSerializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('添加成功!')
else:
return Response(ser_obj.errors) class BookDetailView(APIView):
def get(self, request, pk): # get获取具体某本书的信息
# 1.根据pk去数据库中查询具体的那本书籍对象
book_obj = models.Book.objects.filter(pk=pk).first()
if book_obj:
# 2.将书籍对象 序列化成 json格式的数据
ser_obj = BookModelSerializer(book_obj)
# 3.返回响应
return Response(ser_obj.data)
else:
return Response('无效的书籍id') def put(self, request, pk): # put修改具体某本书的信息
# 1.根据pk去查询具体的那本书籍对象
book_obj = models.Book.objects.filter(pk=pk).first()
if book_obj:
# 2.获取用户发送过来的数据并修改数据
ser_obj = BookModelSerializer(instance=book_obj, data=request.data, partial=True)
if ser_obj.is_valid():
# 3.保存并返回修改后的数据
ser_obj.save()
return Response(ser_obj.data)
else:
return Response(ser_obj.errors)
else:
return Response('无效的书籍id') def delete(self, request, pk): # delete删除具体某一本书籍对象
# 1.根据pk去查询具体的那本书籍对象
book_obj = models.Book.objects.filter(pk=pk).first()
if book_obj:
# 2.删除该书籍对象
book_obj.delete()
return Response('删除成功')
else:
return Response('无效的书籍id')

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

from rest_framework import serializers
from bms import models class PublisherSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField() class BookModelSerializer(serializers.ModelSerializer):
publisher_info = serializers.SerializerMethodField(read_only=True) def get_publisher_info(self, book_obj):
return PublisherSerializer(book_obj.publisher).data class Meta:
model = models.Book
fields = '__all__'
extra_kwargs = {
'publisher': {'write_only': True},
} class PublisherModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Publisher
fields = '__all__'

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

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

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

bms/views.py:

from rest_framework.response import Response
from rest_framework.views import APIView
from bms import models
from bms.modelserializers import BookModelSerializer, PublisherModelSerializer # 通用功能
class GenericView(APIView):
queryset = None
serializer_class = None def get_queryset(self, request, *args, **kwargs):
# 再一次调用all()方法: 让每次请求来的时候都重新查一次数据
return self.queryset.all() def get_obj(self, request, pk, *args, **kwargs):
return self.get_queryset(request, *args, **kwargs).filter(pk=pk).first() # get展示(全部)资源
class ListMixin(object):
def get(self, request):
queryset = self.get_queryset(request)
ser_obj = self.serializer_class(queryset, many=True)
return Response(ser_obj.data) # post添加资源
class CreateMixin(object):
def post(self, request):
ser_obj = self.serializer_class(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('添加成功!')
else:
return Response(ser_obj.errors) # get展示(部分)资源
class RetrieveMixin(object):
def get(self, request, pk, *args, **kwargs):
obj = self.get_obj(request, pk, *args, **kwargs)
if obj:
ser_obj = self.serializer_class(obj)
return Response(ser_obj.data)
else:
return Response('无效的id!') # put更新(修改)资源
class UpdateMixin(object):
def put(self, request, pk, *args, **kwargs):
obj = self.get_obj(request, pk, *args, **kwargs)
if obj:
ser_obj = self.serializer_class(instance=obj, data=request.data, partial=True)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data)
else:
return Response(ser_obj.errors)
else:
return Response('无效的id!') # delete删除资源
class DestroyMixin(object):
def delete(self, request, pk, *args, **kwargs):
obj = self.get_obj(request, pk, *args, **kwargs)
if obj:
obj.delete()
return Response('删除成功!')
else:
return Response('无效的id!') class BookListView(GenericView, ListMixin, CreateMixin):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer class BookDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer class PublisherListView(GenericView, ListMixin, CreateMixin):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer class PublisherDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer

urls.py:

from django.conf.urls import url
from django.contrib import admin
from bms import views urlpatterns = [
url(r'^admin/', admin.site.urls), url(r'^book/$', views.BookListView.as_view()),
url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view()),
url(r'^publisher/$', views.PublisherListView.as_view()),
url(r'^publisher/(?P<pk>\d+)$', views.PublisherDetailView.as_view()),
]

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

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

from rest_framework.viewsets import GenericViewSet

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

bms/views.py:

from rest_framework.response import Response
from bms import models
from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
from rest_framework.viewsets import GenericViewSet # 引入GenericViewSet通用类 # get展示(全部)资源
class ListMixin(object):
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
ser_obj = self.serializer_class(queryset, many=True)
return Response(ser_obj.data) # post添加资源
class CreateMixin(object):
def create(self, request, *args, **kwargs):
ser_obj = self.serializer_class(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('添加成功!')
else:
return Response(ser_obj.errors) # get展示(部分)资源
class RetrieveMixin(object):
def retrieve(self, request, pk, *args, **kwargs):
obj = self.get_object()
if obj:
ser_obj = self.serializer_class(obj)
return Response(ser_obj.data)
else:
return Response('无效的id!') # put更新(修改)资源
class UpdateMixin(object):
def update(self, request, pk, *args, **kwargs):
obj = self.get_object()
if obj:
ser_obj = self.serializer_class(instance=obj, data=request.data, partial=True)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data)
else:
return Response(ser_obj.errors)
else:
return Response('无效的id!') # delete删除资源
class DestroyMixin(object):
def destroy(self, request, pk, *args, **kwargs):
obj = self.get_object()
if obj:
obj.delete()
return Response('删除成功!')
else:
return Response('无效的id!') class BookViewSet(GenericViewSet, ListMixin, CreateMixin, RetrieveMixin, UpdateMixin, DestroyMixin):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer class PublisherViewSet(GenericViewSet, ListMixin, CreateMixin, RetrieveMixin, UpdateMixin, DestroyMixin):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer

urls.py:

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

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

bms/views.py:

from bms import models
from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
from rest_framework.viewsets import ModelViewSet class BookViewSet(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer class PublisherViewSet(ModelViewSet):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer

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

from rest_framework.routers import DefaultRouter
from bms import views urlpatterns = [] router = DefaultRouter()
router.register('book', views.BookViewSet)
router.register('publisher', views.PublisherViewSet) # 重写urlpatterns
urlpatterns += router.urls

DRF(Django REST Framework)框架的更多相关文章

  1. web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 ☝☝☝

    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 ...

  2. DRF Django REST framework APIView(一)

    什么是REST? REST是一个标准,一种规范,遵循REST风格可以使开发的接口通用,便于调用者理解接口的作用. 使url更容易理解,让增删改清晰易懂,在前后端分离开发中按照这一规范能加快开发效率,减 ...

  3. Django REST framework框架介绍和基本使用

    Django REST framework介绍 Django REST framework是基于Django实现的一个RESTful风格API框架,能够帮助我们快速开发RESTful风格的API. 官 ...

  4. Django Rest framework 框架之认证使用和源码执行流程

    用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(Vi ...

  5. Django Rest Framework框架 ---- url控制器

    Django Rest Framework框架 ---- url控制器

  6. 轻轻松松学会 DRF Django REST framework

    据我了解,目前的IT行业的大部分后端开发,都是需要进行前后端分离的,而前后端分类必不可少的是rest 规范,以下是django rest framework的学习路径: DRF Django REST ...

  7. web前端Vue+Django rest framework 框架 生鲜电商项目实战✍✍✍

    web前端Vue+Django rest framework 框架 生鲜电商项目实战  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频 ...

  8. Django Rest framework 框架

    一.开发模式: 1. 普通开发方式(前后端放在一起写) 2. 前后端分离(前后台通过ajaxo交互) 后端(django rest framework写的) <----ajaxo---> ...

  9. DRF Django REST framework 之 解析器(二)

    引入 Django Rest framework帮助我们实现了处理application/json协议请求的数据,如果不使用DRF,直接从 request.body 里面拿到原始的客户端请求的字节数据 ...

  10. DRF (Django REST framework) 中的Request 与 Response

    DRF中的Request 与 Response 1. Request - REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST f ...

随机推荐

  1. 金融数据分析还能这样做?快试试这个BI工具小白也能学会!

    说起银行.保险.股票投资等这些金融行业,大多数人都认为它们都是依靠数据驱动的企业,毕竟大数据的诞生本来就是为了金融信息流通而服务的,但是事实真的是这样吗? 事实并非如此,真正在金融行业做数据分析的人, ...

  2. 【C#TAP 异步编程】异步接口 OOP

    在我们深入研究"异步OOP"之前,让我们解决一个相当常见的问题:如何处理异步方法的继承?那么"异步接口"呢? 幸运的是,它确实可以很好地与继承(和接口)一起使用 ...

  3. selenium+python自动化106 - 滑动 iframe 上的滚动条

    前言 页面嵌套了iframe,这个iframe又是可以滚动的,如何操作iframe上的滚动条? 示例 写一个html页面案例,源码如下 <!DOCTYPE html> <html l ...

  4. ABP Framework 5.2 RC 发布及新增功能介绍

    ABP Framework 5.2 RC 新增功能 目录 ABP Framework 5.2 RC 新增功能 单层解决方案模板 EF Core 数据库迁移 UI 和 数据库 选项 API 版本控制 源 ...

  5. VUE-表单验证

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. typora 使用Markdown语法编辑文本

    MarkDown语法 标题 一级标题# 二级标题## ============= 三级标题### 四级标题 依此类推 Markdown 段落格式 Markdown 段落没有特殊的格式,直接编写文字,段 ...

  7. C++ STL vector扩容原理分析

    扩容特点: 1)新增元素:vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素: 2)对vector的 ...

  8. go1.18泛型的简单尝试

    今天golang终于发布了1.18版本,这个版本最大的一个改变就是加入了泛型.虽然没有在beta版本的时候尝试泛型,但是由于在其他语言的泛型经验,入手泛型不是件难事~ 官方示例 Tutorial: G ...

  9. AT1219题解

    题意 设 \(a\) 的价值为 \(a \times cnt_a\)(\(cnt_a\) 为 \(a\) 在区间中出现的次数),求区间种某种元素,使得这种元素的价值最大. 因为设计出现元素的次数,所以 ...

  10. async-validator 源码学习笔记(二):目录结构

    上一篇文章<async-validator 源码学习(一):文档翻译>已经将 async-validator 校验库的文档翻译为中文,看着文档可以使用 async-validator 异步 ...