drf视图(代码片段)

kend kend     2023-03-08     489

关键词:

目录

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

04drf视图组件(代码片段)

一.视图DjangoRESTframwork提供的视图的主要作用:控制序列化器的执行(检验、保存、转换数据)控制数据库查询的执行1.1视图继承关系1.2视图2个视图基类APIViewGenericAPIView[通用视图类]1.2.1APIViewrest_framework.views.APIViewAPIView是RESTframewor... 查看详情

drf的视图和路由(代码片段)

DRF的视图APIView我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不同呢~~~urlpatterns= [    url(r‘^book$‘,BookView.as_view()),    url(r‘^book/(?P<i 查看详情

drf框架serializer之视图优化(代码片段)

...列化中,我们通过创建序列化器对象的方式大大地简化了视图函数的代码,前端传入的数据通过反序列化操作进行了各种数据校验,代码如下:fromdjango.httpimportJsonResponsefromdjango.viewsimportViewfromdjango.dbimportconnectionimportjsonfrom.modelsim... 查看详情

drf视图类关系详解(代码片段)

...,request._request#3json模块是否执行反序列化bytes格式#4考你:视图类的方法中:self.request,就是当次请求的request#5Response:类,实例化传一堆参,data=字典,status=状态码( 查看详情

drf视图(代码片段)

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

drf序列化器之请求响应以及视图(代码片段)

...ttp请求处理drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作。所以在django原有的django.views.View类基础上,drf封装了多个视图子类出来提供给我们使用。DjangoRESTframwork提供的视图的主要作用:控制序列化器的执... 查看详情

drf4.drf视图开发restfulapi接口(代码片段)

四种方式:函数式编程:functionbasedview类视图:classedbasedview通用类视图:genericclassedbasedviewDRF的视图集Viewsets原生DjangoFBV(Funcitonbasedview)编写,应用的views.pyimportjsonfromdjango.httpimportJsonResponsefromdjango.views.decorators.csrfimportcsrf_exemptcourse... 查看详情

drf之路由系统与视图(代码片段)

手动路由编写#路由fromdjango.conf.urlsimporturlfromapp01.viewsimportUserListViewurlpatterns=[#GET请求查询所有#POST请求增加url(r'^users/$',UserListView.as_view()),url(r'^users.(?P<format>w+)/$',Us 查看详情

学习drf之前(代码片段)

...已经了解过CBV以及FBV什么是FBV和CBV呢~~  FBV基于函数的视图  CBV基于类的视图也就是说我们是用函数编写视图~还是类编写视图~~我们来看下两个的简单实现~~urlpatterns=[path(‘admin/‘,admin.site.urls),path(‘test_fbv‘,t 查看详情

drf视图和路由(代码片段)

APIView:在django中写CBV的时候是继承View,rest_framework继承的是APIView,这两种具体有什么不同呢?urlpatterns=[url(r‘^book$‘,BookView.as_view()),url(r‘^book/(?P<id>d+)$‘,BookEditView.as_view()),]无论是View还是APIView最开始调用的都是as_ 查看详情

0802drf视图(代码片段)

昨日回顾:1.Serializer(序列化)1.ORM对应的query_set和ORM对象转换成JSON格式的数据1.在序列化类中定义自定义的字段:SerializerMethodField在类中定义get_自定义字段名(self,obj)方法2.read_only只在显示(查询)时才会有效。2.对前端POST过来的... 查看详情

drf之视图组件(代码片段)

不断的优化我们写的程序,是每个程序员必备的技能和职业素养,也是帮助我们成长的非常重要的手段。相关知识点相关知识点一:RESTfulapi接口规范我给大家总结的REST的最重要的一句话,那就是:url用来唯一定位资源,http请求... 查看详情

drf视图家族(代码片段)

drf视图家族视图家族- 视图基类,视图工具类,工具视图类,视图集视图基类:APIView、GenericAPIView视图工具类:mixins包下的五个类(六个方法)工具视图类:generics包下的所有GenericAPIView的子类视图集:viewsets包下的类generics中... 查看详情

drf入门规范(代码片段)

...化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。 查看详情

django-rest-framework---总结(代码片段)

...与反序列化整合(重点)3.整体单改4.单与整体局部修改视图类视图类传递参数给序列化类二次封装Response类视图家族GenericAPIView基类mixins视图工具集-辅助GenericAPIView工具视图视图集GenericAPIView与APIView最为两大继承视图的区别工具... 查看详情

drf框架之视图的扩展类简介(代码片段)

...架,为我们提供的试图扩展类的使用方法即作用。在使用视图扩展类时,需要将mixins模块导入到view文件中。fromrest_frameworkimportmixins并且,在使用视图扩展类时,必须结合GenericAPIView基类一起使用。所谓,视图的扩展类,就是Generi... 查看详情

drf视图组件(代码片段)

一基本视图写一个出版社的增删查改resful接口 路由:url(r‘^publish/$‘,views.PublishView.as_view()),url(r‘^publish/(?P<pk>d+)/$‘,views.PublishDetailView.as_view()),视图:classPublishSerializers(serializers.ModelSerializer):classMeta:model=models.Publishfields=‘_... 查看详情

drf-视图集路由系统action装饰器(代码片段)

1.9个视图扩展类1.两个视图基类:APIView、GenricAPIView2.5个视图扩展类:CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,ListModelMixin,DestroyModelMixin3.9个视图子类:CreateAPIView,DestroyAPIView,ListAPIView,RetrieveAPIView,UpdateAPIView,ListCreateAPIView,RetrieveDestroyAPIVi... 查看详情