DRF(Django REST Framework)框架

目录

  • 一.DRF中的Request
  • 二.前戏: 关于面向对象的继承
  • 三.初级版本
    • 1. settings.py文件 -- 注册app
    • 2. models.py文件 -- 创建表
    • 3. admin.py文件
    • 4. 根目录下urls.py -- 路由匹配
    • 5. bms/views.py -- 视图函数
    • 6. bms/modelserializers.py -- 自定义序列化工具
  • 四.进化版: 使用自定义混合类和自定义通用类
  • 五.超级进化版: 使用GenericViewSet通用类
  • 六.究极进化版: 使用rest_framework帮我们封装好的通用类和混合类
  • 七.终极进化版: 使用rest_framework帮我们封装好的路由DefaultRouter

一.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

原文地址:https://www.cnblogs.com/bigox/p/11634649.html

时间: 2024-10-08 03:24:29

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

DRF (Django REST framework) 框架介绍

Web应用模式 在开发Web应用中,有两种应用模式: 前后端不分离 前后端分离 1 前后端不分离 在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高. 这种应用模式比较适合纯网页应用,但是当后端对接App时,App可能并不需要后端返回一个HTML网页,而仅仅是数据本身,所以后端原本返回网页的接口不再适用于前端App应用,为了对接App后端还需再开发一套接口. 2 前后端分离 在前后端分离的应用模式中,后端仅返

DRF (Django REST framework) 框架介绍(2)

环境安装与配置 DRF需要以下依赖: Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6) Django (1.10, 1.11, 2.0) DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建.(若没有Django环境,需要先创建环境安装Django) 1. 安装DRF pip install djangorestframework 2. 添加rest_framework应用 我们利用在Django框架学习中创建的demo工

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

web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 1.drf前期准备 1.django-rest-framework官方文档 https://www.django-rest-framework.org/ #直接百度找到的djangorestframework的官网是打不开的 2.安装依赖包 如图所示,django restframework的依赖模块,除了coreapi和django-guardian,已经在前面安装过了. 打开终端,执行安装命令

Django REST framework框架详解

Django REST framework 简介 在序列化与反序列化时,虽然操作的数据不尽相同,但是执行的过程却是相似的,也就是说这部分代码是可以复用简化编写的. 在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增.删.改.查的实现流程基本套路化,所以这部分代码也是可以复用简化编写的: 增:校验请求数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回 删:判断要删除的数据是否存在 -> 执行数据库删除 改:判断要修改的数据是否存在 -&g

轻轻松松学会 DRF Django REST framework

DRF Django REST framework 之 APIView(一) DRF Django REST framework 之 解析器(二) DRF Django REST framework 之 序列化(三) DRF Django REST framework 之 视图组件(四) 持续更新中.... 原文地址:https://www.cnblogs.com/pungchur/p/12028316.html

Django Rest framework 框架

用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(View): pass # 订单View继承了APIView,相当于这个订单里面的功能就更多了. class OrderView(APIView): pass restframework from rest_framework.views import APIView 这个APIView继承View 这

DRF Django REST framework 之 认证组件(五)

引言 很久很久以前,Web站点只是作为浏览服务器资源(数据)和其他资源的工具,甚少有什么用户交互之类的烦人的事情需要处理,所以,Web站点的开发这根本不关心什么人在什么时候访问了什么资源,不需要记录任何数据,有客户端请求,我即返回数据,简单方便,每一个http请求都是新的,响应之后立即断开连接. 而如今,互联网的世界发生了翻天覆地的变化,用户不仅仅需要跟其他用户沟通交流,还需要跟服务器交互,不管是论坛类.商城类.社交类.门户类还是其他各类Web站点,大家都非常重视用户交互,只有跟用户交互了,才能

DRF Django REST framework 之 视图组件(四)

引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 使用视图组件的mixin优化接口逻辑 导入 mixins 定义序列化类 定义视图类 # 1.导入mixins from rest_framework.mixins import ( ListModelMixin, CreateModelMixin, DestroyModelMixin, Update

DRF Django REST framework 之 频率,响应器与分页器组件(六)

频率组件 频率组件类似于权限组件,它判断是否给予请求通过.频率指示临时状态,并用于控制客户端可以向API发出的请求的速率. 与权限一样,可以使用多个调节器.API可能会对未经身份验证的请求进行限制,而对于经过身份验证的请求则进行限制较少. 例如,可以将用户限制为每分钟最多60个请求,每天最多1000个请求. 自定义频率组件 使用方式与权限,认证组件几乎相同 该方式没有DRF提供的方式简洁 import time import math from rest_framework import exc

Django REST framework 简介

Django REST framework 简介1.在序列化与反序列化时,虽然操作的数据不尽相同,但是执行的过程却是相似的,也就是说这部分代码是可以复用简化编写的.2.在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增.删.改.查的实现流程基本套路化,所以这部分代码也是可以复用简化编写的: 增:校验请求数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回删:判断要删除的数据是否存在 -> 执行数据库删除改:判断要修改的数据是否存在 -&g