首页 > 解决方案 > 多个模型的通用 API 声明

问题描述

在使用 Django 开发 JWT 应用程序的过程中,我注意到了 CRUD API 视图的声明模式,例如:

class Create(generics.CreateAPIView):
    queryset = <some django model>.objects.all()
    serializer_class = serializer # <some serializer class>


class Read(generics.ListAPIView):
    queryset = <some django model>.objects.all()
    serializer_class = serializer # <some serializer class>


class Update(generics.RetrieveUpdateAPIView):
    queryset = <some django model>.objects.all()
    serializer_class = serializer # <some serializer class>


class Delete(generics.DestroyAPIView):
    queryset = <some django model>.objects.all()
    serializer_class = serializer # <some serializer class>

考虑到我的具体项目有 7 个模型必须具有这些功能,而不是声明上述类的 28 个版本,我认为如果有这样的类会更优雅:

class Create(generics.CreateAPIView):
    def __init__(self, model, serializer):
        self.queryset = model.objects.all()
        self.serializer_class = serializer
        super().__init__()


class Read(generics.ListAPIView):
    def __init__(self, model, serializer):
        self.queryset = model.objects.all()
        self.serializer_class = serializer
        super().__init__()


class Update(generics.RetrieveUpdateAPIView):
    def __init__(self, model, serializer):
        self.queryset = model.objects.all()
        self.serializer_class = serializer
        super().__init__()


class Delete(generics.DestroyAPIView):
    def __init__(self, model, serializer):
        self.queryset = model.objects.all()
        self.serializer_class = serializer
        super().__init__()

class CRUD:
    """Base class for CRUD Operations"""

    def __init__(self, model, serializer):
        self.create = Create(model, serializer)
        self.read = Read(model, serializer)
        self.update = Update(model, serializer)
        self.delete = Delete(model, serializer)

紧随其后的是那些实例:

Reg_API = CRUD(Registry, RegistrySerializer)
Tag_API = CRUD(Tag, TagSerializer)
# etc

如果我在 上进行测试python manage.py shell,该实例Reg_API.create.queryset将准确返回我需要的内容。但是,如果我跑步python manage.py runserver并尝试访问该路线,我会得到__init__() missing 2 required positional arguments: 'model' and 'serializer'...

在 urls.py 我的路线定义为:

from .crud import Reg_API

urlpatterns = [
    path('api/registry/create', Reg_API.create.as_view())
]

所以我想知道这里缺少什么。有什么我忘记了,或者有什么理由我应该遵循 28 声明方式?

标签: pythondjangorestdjango-rest-frameworkcrud

解决方案


您正在尝试重新设计已经存在的功能。您想要实现的目标已经存在于 DRF 中,称为viewset。对于您的情况,此代码足以满足整个 Registry CRUD API 的需求:

from rest_framework import viewsets


class RegistryViewSet(viewsets.ModelViewSet):
    queryset = Registry.objects.all()
    serializer_class = RegistrySerializer

然后在你的 urls.py 中:

from myapp.views import RegistryViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'registry', RegistryViewSet, basename='registry')
urlpatterns = router.urls

推荐阅读