Django rest framework гнездование двух или более наборов представлений вместо отображения пользовательских действий с помощью декоратора @action

Итак, давайте представим, что я пытаюсь создать API для крошечного приложения чата. Представьте, что у меня есть 2 модели в моем Django проекте, одна для сообщений, а другая для групп. Каждая группа может иметь несколько сообщений, но одно сообщение относится только к одной группе (получается связь "один ко многим").

вот модели:

class Group(models.Model):
    title = models.CharField(max_length=250)

    def get_messages(self):
        return self.messages.all()

class Message(models.Model):
    body = models.TextField()
    group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name="messages")

У меня есть следующие наборы представлений Django Rest Framework ViewSets:

class GroupViewset(viewsets.ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer


class MessageViewset(viewsets.ModelViewSet):
    queryset = Message.objects.all()
    serializer_class = MessageSerializer

Viewsets - это здорово! Только с помощью этих нескольких строк у меня теперь есть полные CRUD-операции для экземпляров Group и Message! Мне просто нужно получить доступ к следующим маршрутам:

/groups/ -> Для выполнения операций GET, POST для экземпляров группы /groups/<group_pk>/ -> Для выполнения операций GET, PUT, PATCH, DELETE для экземпляров группы

/messages/ -> Для выполнения операций GET, POST для экземпляров Message /messages/<message_pk>/ -> Для выполнения операций GET, PUT, PATCH, DELETE для экземпляров Message

но поскольку сообщение относится к группе, и я могу получить все сообщения группы, выполнив GroupObject.get_messages(), я ищу лучший способ вложить Viewsets.

Вместо маршрутов сообщений, которые я указал ранее, я хочу иметь следующие маршруты:

/groups/ -> Для выполнения операций GET, POST для экземпляров группы /groups/<group_pk>/ -> Для выполнения операций GET, PUT, PATCH, DELETE для экземпляров группы

/groups/<group_pk>/messages/ -> Для выполнения операций GET, POST для экземпляров сообщений, относящихся к группе с <group_pk> informed.

/groups/<group_pk>/messages/<message_pk>/ -> Для операций GET, PATCH, PUT и DELETE над экземпляром Message с <message_pk>, который относится к экземпляру Group с <group_pk>

Но вот в чем дело... мне уже удалось это сделать! Проблема в том, что я чувствую, что я не совсем "DRY" в моих наборах представлений... слишком много повторений кода, плюс, для каждого нового @action я должен делать все сам, теряя силу ModelViewset, и так как у меня есть MessageViewset, я ищу способ использовать его поверх моего GroupViewset.

Вот как я это делаю на данный момент:

class GroupViewset(viewsets.ModelViewSet):

    queryset = Group.objects.all()
    serializer_class = GroupSerializer

    @action(detail=True, methods=["get"])
    def messages(self, request, pk=None):

        group = self.get_object()
        queryset = group.get_messages()

        message_serializer = MessageSerializer(queryset, many=True)
        return Response(message_serializer.data)

    @messages.mapping.post
    def messages_create(self, request, pk=None):
        ...

    @action(detail=True, methods=["get"], url_path=r"notes/(?P<message_pk>[^/.]+)")
    def messages_retrieve(self, request, pk=None, message_pk=None):
        ...

    @messages_retrieve.mapping.put
    def messages_update(self, request, pk=None, message_pk=None):
        ...

    @messages_retrieve.mapping.patch
    def messages_partial_update(self, request, pk=None, message_pk=None):
        ...
        
    @messages_retrieve.mapping.delete
    def messages_delete(self, request, pk=None, message_pk=None):
        ...

Есть ли способ вложить MessageViewset в GroupViewset так, чтобы мне не нужно было отображать все методы через @action, как я это делаю? Отображение через @action работает, но это слишком много работы и повторения кода...

Вернуться на верх