如何使用rest框架在Django上编写通用CRUD服务?

时间:2019-07-18 10:36:53

标签: django-rest-framework

我是django的新人,在尝试编写简单服务时遇到了一些问题。

  1. 我要做什么? 我打算使用rest-framework库为我的模型编写一个通用的crud服务。 我不想为所有模型编写序列化程序和视图,也不想尝试优化代码并学习一些有用的知识。
  2. 我的模型 假设我有一个抽象的BaseBusinessObject

    class BaseBusinessObject(models.Model):
    
        CreatedAt = models.DateField()
        UpdatedAt = models.DateField()
    
        class Meta:
            abstract = True
    
    

    我还有很多具体的类,它们是从基类继承的:

    class Product(BaseBusinessObject):
         Description: models.TextField()
         Type: models.CharField()
    
    ....
    
    class Company(BaseBusinessObject):
        Title: models.CharField()
    
    ....
    
    class Person(BaseBusinessObject):
        Name: models.CharField()
    

    以此类推

3。我想要什么? 我已经弄清楚了,利用其余框架,我可以创建序列化器和视图,然后为url ... / Product,... / Company,... / Person注册路由器。但是,如果我有1000堂课怎么办?这很无聊

A。如何动态指定子对象的网址?我不想对方法进行硬编码,我正在寻找解决方案...类似这样的东西: ... / api / Entities / ClassName

B。然后如何在django-rest-framework中使用动态创建的URL?

    router.register('persons', PersonViewSet)

如何用更通用的方式编写它?

    router.register('<ClassName>', <GenericViewSet>)

C。使用DRF,我可以为模型中的每个具体类创建视图集:

    class PersonViewSet(viewsets.ModelViewSet):
    queryset = Person.objects.all()
    serializer_class = PersonSerializer

但是正如我说的,我有很多课。如何以更通用的方式编写它? 我试图为抽象类创建视图集,但是在查询抽象对象时会遇到一些麻烦。

是否可以为抽象类创建这样的服务,然后其所有子级简单地(或不简单地)继承CRUD方法? 我可以尝试为序列化程序和视图集编写工厂吗? 我可以采取哪些可能的解决方案来解决我的问题?

2 个答案:

答案 0 :(得分:0)

我建议使用查询参数代替路径参数,然后只需注册一个URL并处理请求的各个元素,然后将其正确路由到服务器端。 When do I use path params vs. query params in a RESTful API?

答案 1 :(得分:0)

经过两天的走动,我终于找到了解决方案。可能是其他人会遇到一些问题,所以我试图解释我已经做过的事情。

首先,我在django项目中创建一个“基本”应用程序,并将其添加到settings.py。然后,我在models.py中创建一个抽象类:

class BaseCrudEntity(models.Model):
    pass
    class Meta:
        abstract = True

我想为所有“业务”类的CRUD操作编写通用服务。 问题是我不想为它们编写序列化器和视图-我想动态地动态创建它们。我决定也使用django rest框架,因为我不打算再创建一个自行车。 我决定继承该抽象类中的所有“业务”类,并为所有可能的“家庭”编写服务

因此,我必须创建一个负责VeiwSet创建的结构。 这是我的view.py:

class BaseCrudViewSetFabric():

    @classmethod
    def CreateViewSet(self, _context):
        classname = _context.__name__ + 'ViewSet'
        return type(classname, (viewsets.ModelViewSet,), {
            'queryset':_context.objects.all(),
            'serializer_class':BaseCrudSerializerFabric.CreateSrializer(_context)
        })
        pass

此处_context-描述我模型的具体类的变量。 如您所见,此函数根据我的上下文创建一个具体的ViewSet。在其中调用了Serializers结构。 这是我的serializers.py的代码:

class BaseCrudSerializerFabric():

    @classmethod
    def CreateSrializer(self, _context):
        classname = _context.__name__
        _Meta = type('Meta', (), {'model':_context,'fields':'__all__'})
        _crudserializer = type(
            classname,
            (serializers.ModelSerializer,),
            {'Meta': _Meta}        
        )
        return _crudserializer

此外,我必须编写用于动态路由的服务-我不想对网址进行硬编码。 这里是来自核心项目的示例ursl.py:

from base.urls import router
url(r'^api/v1/', include(router.urls))

并来自base / urls.py:

from rest_framework.routers import DefaultRouter, SimpleRouter
from base.models.BaseCrudEntity import BaseCrudEntity
from base.views.basecrud_view import BaseCrudViewSetFabric

class CustomRouter(SimpleRouter):

    def RoutRegister(self):
        childs = getChilds(BaseCrudEntity)
        #print(childs)
        for ch in childs:
            if (ch._meta.abstract == False):
                #print(ch.__name__)
                prefix = ch.__name__
                self.register(prefix, BaseCrudViewSetFabric.CreateViewSet(ch))
        return(self)
    pass

router = CustomRouter()
router.RoutRegister()

最后,我只是创建一些具体模型:

from django.db import models
from base.models.BaseCrudEntity import BaseCrudEntity

class Person(BaseCrudEntity):

    Name = models.CharField(max_length = 255)
    Surname = models.CharField(max_length = 255)
    Patronymic = models.CharField(max_length = 255, null = True)
    DateOfBirth = models.DateField(null = True)
    #slug = models.SlugField(default = 'hui', editable = False)

    def __str__(self):
        return "{} {} {}".format (self.Surname, self.Name, self.Patronymic)

仅此而已。 当应用程序启动时,它为http://127.0.0.1:8000/api/v1/Person注册一条路由,并创建序列化程序和视图集,因此也将提供Django-Rest Framework提供的所有CRUD操作。