Django Rest Framework:使用新路由更新子对象,而不是部分更新模型



我正在尝试创建一个API对象Roster,该对象上有一个成员列表作为子对象。但是,我不想通过部分更新 Roster 对象来更新子对象 - 相反,我想要"添加成员"和"删除成员"的路由。

目标:

GET /Roster/{ROSTERID}

响应正文:

{
id: {roster id},
members: # members sub object is read only
[
{member subobject},
{member subobject},
...
],
}

POST /Roster/{RosterID}/AddMember

{
{member id},
{member id}, ...
}

然后是删除成员的类似事情。

注意:我希望能够传入现有的成员 ID。我不想在这里创建新成员。

我应该在文档中寻找什么,以便能够添加路由以使用用户 ID 更新成员列表,而不必传入整个用户对象?

serializers.py

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'groups']
class RosterSerializer(serializers.ModelSerializer):
members = serializers.ListField(
child=UserSerializer()
)
class Meta:
model = Roster
fields = ('id', 'name', 'members')
depth = 2

app/models.py

class Members(User):
on_pto = models.BooleanField(default=False)
class Roster(models.Model):
objects = models.Manager()
name = models.CharField(max_length=80, blank=True, default='', unique=True, null='')
members = models.ForeignKey(
Members,
limit_choices_to={'on_pto': False},
blank=True,
null=True,
related_name='members',
on_delete=models.CASCADE
)

views.py

class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer

class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all().order_by('-id')
serializer_class = GroupSerializer

class RosterViewSet(viewsets.ModelViewSet):
""""""
queryset = Roster.objects.all().order_by('-id')
serializer_class = RosterSerializer

您可能需要更改模型以允许多个成员进入名单,要么对名单执行多对多操作,要么将 FK 关系放在用户身上。因此,您可以为名单添加多个成员。

为此,您可以使用这样的自定义路由。下面显示add_member,然后类似地显示remove_member,修改以从members_set中删除名单对象。

class RosterViewSet(viewsets.ModelViewSet):
queryset = Roster.objects.all().order_by('-id')
serializer_class = RosterSerializer
@action(detail=True, methods=['post'])
def add_member(self, request, pk=None):
errors = []
response = {}
roster = self.get_object()
members_dict = request.data['members']
if not isinstance(members_dict, list):
errors.append("Invalid request format")
else:
for id in members_dict:
try:
member = User.objects.get(pk=id)
roster.members.add(member)
roster.save()
status_code = status.HTTP_200_OK
except Member.DoesNotExist:
errors.append("Member id {} not found".format(id))
if errors:
response['errors'] = errors
status_code = status.HTTP_400_BAD_REQUEST
return response.Response(response, status=status_code)

最新更新