在 django rest 框架中保存嵌套的单个对象
Saving nested single object in django rest framework
我有 3 个对象 - 公司、专家和 RecentProject,其中 RecentProject 具有公司的外键和专家的多对多关系:
class RecentProject(BaseProfileObject):
company = models.ForeignKey(
'experts.Company',
verbose_name=_("Company"),
blank=True,
null=True,
related_name='projects')
experts = models.ManyToManyField(
"Expert",
verbose_name=_("Experts"),
blank=True,
null=True,
related_name='projects')
class Meta:
verbose_name = _("Recent project")
verbose_name_plural = _("Recent projects")
我想要的是能够从像
这样的端点post最近的新项目
api/v1/companies/1/recentprojects/ 和 api/v1/experts/1/recentprojects/
在第一种情况下,序列化程序应该能够验证(或者更确切地说,进行权限检查)用户是否可以对公司进行更改,在第二种情况下,用户是否可以对专家进行更改。
我似乎找不到的是如何让权限了解父对象的示例(第一种情况是公司,第二种情况是专家)。
我知道这可以通过权限来完成,所以我创建了如下权限:
class UserCanModifyCompany(permissions.BasePermission):
def has_permission(self, request, view):
# Do check here
return False
然后我将它添加到我的视图集中:
class最近的项目视图集(viewsets.ModelViewSet):
查询集 = RecentProject.objects.all()
serializer_class = RecentProjectSerializer
@permission_classes((UserIsAuthenticatedExpert, UserCanModifyCompany))
def create(self, request, *args, **kwargs):
return super(RecentProjectViewSet, self).create(request, *args, **kwargs)
@permission_classes((UserIsAuthenticatedExpert, UserCanModifyCompany))
def update(self, request, *args, **kwargs):
return super(RecentProjectViewSet, self).update(request, *args, **kwargs)
但是我如何确保权限检查具有可用于 company/expert 访问检查的信息。或者我是否需要为两个 company/expert 最近保存的项目创建不同的视图集并为它们都具有不同的权限 classes?
首先,为同一资源创建两个不同的端点不是一个好主意。我建议您使用单端点:api/v1/recentprojects/
。
话虽如此,我也遇到过类似情况,我认为你最好的选择是在 公司和专家视图集 上使用 @detail_route
.
例如,在您的 ExpertViewSet
:
@detail_route(methods=['post'], , permission_classes=[UserIsAuthenticatedExpert, UserCanModifyCompany])
def recentprojects(self, request, pk=None):
expert = self.get_object()
serializer = RecentProjectSerializer(data=request.data)
if serializer.is_valid():
recent_project = serializer.save(company=somecompany)
recent_project.experts.add(expert)
return Response({'status': 'ok'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
这将使您 post 新的近期项目成为 api/v1/experts/{pk}/recentprojects/
。
至于权限,你需要实现 has_object_permission
因为这是一个单一的对象端点:
class UserIsAuthenticatedExpert(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return some_condition
您还可以覆盖 get_queryset
和 self.action
以过滤端点可以操作的 Expert 或 Company 实例,但这会引发 404 错误而不是 403。
我有 3 个对象 - 公司、专家和 RecentProject,其中 RecentProject 具有公司的外键和专家的多对多关系:
class RecentProject(BaseProfileObject):
company = models.ForeignKey(
'experts.Company',
verbose_name=_("Company"),
blank=True,
null=True,
related_name='projects')
experts = models.ManyToManyField(
"Expert",
verbose_name=_("Experts"),
blank=True,
null=True,
related_name='projects')
class Meta:
verbose_name = _("Recent project")
verbose_name_plural = _("Recent projects")
我想要的是能够从像
这样的端点post最近的新项目api/v1/companies/1/recentprojects/ 和 api/v1/experts/1/recentprojects/
在第一种情况下,序列化程序应该能够验证(或者更确切地说,进行权限检查)用户是否可以对公司进行更改,在第二种情况下,用户是否可以对专家进行更改。 我似乎找不到的是如何让权限了解父对象的示例(第一种情况是公司,第二种情况是专家)。
我知道这可以通过权限来完成,所以我创建了如下权限:
class UserCanModifyCompany(permissions.BasePermission):
def has_permission(self, request, view):
# Do check here
return False
然后我将它添加到我的视图集中: class最近的项目视图集(viewsets.ModelViewSet): 查询集 = RecentProject.objects.all() serializer_class = RecentProjectSerializer
@permission_classes((UserIsAuthenticatedExpert, UserCanModifyCompany))
def create(self, request, *args, **kwargs):
return super(RecentProjectViewSet, self).create(request, *args, **kwargs)
@permission_classes((UserIsAuthenticatedExpert, UserCanModifyCompany))
def update(self, request, *args, **kwargs):
return super(RecentProjectViewSet, self).update(request, *args, **kwargs)
但是我如何确保权限检查具有可用于 company/expert 访问检查的信息。或者我是否需要为两个 company/expert 最近保存的项目创建不同的视图集并为它们都具有不同的权限 classes?
首先,为同一资源创建两个不同的端点不是一个好主意。我建议您使用单端点:api/v1/recentprojects/
。
话虽如此,我也遇到过类似情况,我认为你最好的选择是在 公司和专家视图集 上使用 @detail_route
.
例如,在您的 ExpertViewSet
:
@detail_route(methods=['post'], , permission_classes=[UserIsAuthenticatedExpert, UserCanModifyCompany])
def recentprojects(self, request, pk=None):
expert = self.get_object()
serializer = RecentProjectSerializer(data=request.data)
if serializer.is_valid():
recent_project = serializer.save(company=somecompany)
recent_project.experts.add(expert)
return Response({'status': 'ok'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
这将使您 post 新的近期项目成为 api/v1/experts/{pk}/recentprojects/
。
至于权限,你需要实现 has_object_permission
因为这是一个单一的对象端点:
class UserIsAuthenticatedExpert(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return some_condition
您还可以覆盖 get_queryset
和 self.action
以过滤端点可以操作的 Expert 或 Company 实例,但这会引发 404 错误而不是 403。