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 работает, но это слишком много работы и повторения кода...