我是django的新人,在尝试编写简单服务时遇到了一些问题。
我的模型 假设我有一个抽象的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方法? 我可以尝试为序列化程序和视图集编写工厂吗? 我可以采取哪些可能的解决方案来解决我的问题?
答案 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操作。