DRF视图组件(2个视图基类、5个视图扩展类、9个视图子类、视图集和路由映射)

DRF视图组件(2个视图基类、5个视图扩展类、9个视图子类、视图集和路由映射)

2个视图基类

  • APIView
  • GenericAPIView

APIView写法:

from rest_framework.views import APIView


class publish(APIView):
    def get(self, request):
        publish_obj = models.Publish.objects.all()
        serializer = PublishSerializer(instance=publish_obj, many=True)
        return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})

    def post(self, request):
        serializer = PublishSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'code': '200', 'msg': '添加成功', 'result': serializer.data})
        else:
            return Response({'code': '900', 'msg': serializer.errors})


class publish_detail(APIView):
    def get(self, request, u_id):
        publish_obj = models.Publish.objects.get(id=u_id)
        serializer = PublishSerializer(instance=publish_obj)
        return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})

    def delete(self, request, u_id):
        pass

    def put(self, request, u_id):
        publish_obj = models.Author.objects.filter(pk=u_id).first()
        # 改对象必须传data和instance
        serializer = PublishSerializer(instance=publish_obj, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'code': '200', 'msg': "修改成功", 'result': serializer.data})
        else:
            return Response({'code': '201', 'msg': serializer.errors})

GenericAPIView类改写:

from rest_framework.generics import GenericAPIView


class publish(GenericAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request):
        publish_obj = self.get_queryset()
        serializer = self.get_serializer(instance=publish_obj, many=True)
        return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'code': '200', 'msg': '添加成功', 'result': serializer.data})
        else:
            return Response({'code': '900', 'msg': serializer.errors})


class publish_detail(GenericAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request, pk):
        publish_obj = self.get_object()
        serializer = self.get_serializer(instance=publish_obj)
        return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})

    def delete(self, request, pk):
        self.get_object().delete()
        return Response({'code': '200', 'msg': '删除成功'})

    def put(self, request, pk):
        publish_obj = self.get_object()
        # 改对象必须传data和instance
        serializer = self.get_serializer(instance=publish_obj, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'code': '200', 'msg': "修改成功", 'result': serializer.data})
        else:
            return Response({'code': '201', 'msg': serializer.errors})
  • queryset = models.Publish.objects.all():查询所有数据
  • serializer_class = PublishSerializer:获取序列化类(本文未展示)
  • publish_obj = self.get_queryset():获取所有数据
  • serializer = self.get_serializer(instance=publish_obj, many=True):使用定义好的序列化类
  • self.get_object():这里不需要传入pk,直接用它定义好的方法,但是它默认识别的只有pk,取其他名会报错

mixins的5个视图扩展类

  • CreateModelMixin:新增

  • ListModelMixin:查询所有

  • DestroyModelMixin:删除单条

  • UpdateModelMixin:修改单条

  • RetrieveModelMixin:查询单条

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin, ListModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    UpdateModelMixin
    
    
class publish(GenericAPIView, CreateModelMixin, ListModelMixin):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request):
        res = super().list(request)
        return Response({'code': '200', 'msg': '查询成功', 'result': res.data})

    def post(self, request):
        res = super().create(request)
        print(type(res))
        return Response({'code': '200', 'msg': '添加成功', 'result': res.data})


class publish_detail(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request, *args, **kwargs):
        res = super().retrieve(request, *args, **kwargs)
        return Response({'code': '200', 'msg': '查询成功', 'result': res.data})

    def delete(self, request, *args, **kwargs):
        res = super().destroy(request, *args, **kwargs)
        return Response({'code': '200', 'msg': '删除成功'})

    def put(self, request, *args, **kwargs):
        res = super().update(request, *args, **kwargs)
        return Response({'code': '200', 'msg': "修改成功", 'result': res.data})
  • res = super().list(request):调用ListModelMixin类中的list方法可以省去查询数据和序列化的书写,下面的都一样
  • 注:res是一个 Response 实例,而不是一个序列化器实例,因此对返回值调用 .is_valid()之类的方法会报AttributeError

generics的9个视图子类

注意要继承ViewSetMixin类,与GenericViewSet不同,他会帮你把接口全部写好,只需自己写序列化类就行

  • CreateAPIView:新增
  • DestroyAPIView:删除
  • ListAPIView:查询所有
  • ListCreateAPIView:查询所有和新增的合并
  • RetrieveAPIView:查询单个
  • RetrieveDestroyAPIView:查询单个和删除的合并
  • RetrieveUpdateAPIView:查询单个和修改的合并
  • RetrieveUpdateDestroyAPIView:查询单个、修改和删除的合并
  • UpdateAPIView:修改
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
    
    
class publish(ViewSetMixin, ListCreateAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

class publish_detail(ViewSetMixin, RetrieveUpdateDestroyAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

ViewSetMixin自定义重写内容

  1. get_queryset(self):用于返回视图中所使用的查询集。可以重写该方法来返回定制的查询集,以满足特定的需求
  2. get_serializer_class(self):用于返回视图中所使用的序列化器类。可以根据不同的条件返回不同的序列化器类
  3. get_serializer_context(self):返回传递给序列化器的上下文数据。可以包含请求对象、视图参数等信息
  4. list(self, request, *args, **kwargs):在重写的 list 方法中,可以获取原始响应对象,添加自己想要的自定义信息,然后返回修改后的响应,可以在 ListAPIView 中使用
  5. create(self, request, *args, **kwargs):用于处理创建资源的逻辑,可以在 ListCreateAPIView 中使用
  6. retrieve(self, request, *args, **kwargs):用于处理检索单个资源的逻辑,可以在 RetrieveAPIView 中使用
  7. update(self, request, *args, **kwargs):用于处理更新资源的逻辑,可以在 UpdateAPIView 中使用
  8. destroy(self, request, *args, **kwargs):用于处理删除资源的逻辑,可以在 DestroyAPIView 中使用
示例
def list(self, request, *args, **kwargs):
    response = super().list(request, *args, **kwargs)
    response['Access-Control-Allow-Origin'] = '*'

    return response

视图集

# views.py
from rest_framework.viewsets import ModelViewSet

class publish(ModelViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer
# urls.py
from django.contrib import admin
from django.urls import path
from app import views

urlpatterns = [
    path('publish/', views.publish.as_view({'get': 'list', 'post': 'create'})),
    path('publish/<str:pk>/', views.publish.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
  • 此时就不需要再分一个publish_detail类了,ModelviewSet已经帮你把五个接口全部写好了,只需在路由层添加映射
  • 'get': 'list':表示遇到get请求时执行list方法,其他的也是

视图集中重写序列化和反序列化

def register(self, request):
    username = (request.data.get('username'))
    password = (request.data.get('password'))
    if UserInfo.objects.filter(username=username):
        return Response(f'用户{username}已存在')
    # 重写序列化规则
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response('注册成功')
def change(self, request, *args, **kwargs):
    # 重写反序列化并创建update
    serializer = ChangePassword(data=request.data, instance=UserInfo.objects.get(pk=kwargs.get('pk')))
    if serializer.is_valid():
        return Response(serializer.data)

自定制返回格式

  • 不管是视图子类还是视图集,需要自定制返回字段时只需重写所需方法就行

  • 例如我要自定制查询所有的返回值就重写list:

class publish(ListCreateAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer

    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        res.data = {"code": 200, "msg": "查询成功", "result": res.data}
        return Response(res.data)
  • res.data默认返回的是一个包含多个字典的列表

自动生成路由(SimpleRouter)

# urls.py
from rest_framework.routers import SimpleRouter
from app import views

# 实例对象
router = SimpleRouter()
# 将publish类注册,最左边的publish为浏览器输入的路由,最右边的publish是别名
router.register('publish', views.publish, 'publish')

urlpatterns = [
]

urlpatterns += routers.urls
# 将注册好的路由添加进urlpatterns

现在得到的路由其实就是http://127.0.0.1:8000/publish/,调用的视图类是publish,并且pk它也会自动帮你写好

与SimpleRouter类似的还有DefaultRouter,他俩基本用法完全一致,唯一不同的是DefaultRouter会返回一个根路径

  • SimpleRouter
image-20240415205837533
  • DefaultRouter
image-20240415205916923 点进`Api Root`后可以看到它返回了一个根路径
{
    "publish": "http://127.0.0.1:8000/publish/"
}

action装饰器

SimpleRouter自动生成路由后有一个弊端就是当绑定的类中没有get\path这种方法名时会注册失败

例如我现在有一个login方法,我想让他接受get请求实现查询单个的功能要,只需在上面价加个action装饰器

# views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action

class publish(ModelViewSet):
    
    @action(methods=['GET'], detail=False)
    def login(self, request)

action参数:(methods=None, detail=None, url_path=None, url_name=None, **kwargs):

  • methods:包含被允许的请求方法
  • detail:指定是否需要提供对象的详细信息
  • url_path:指定自定义的 URL 路径
  • url_name:指定自定义的 URL 名称
  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值