idegree
@idegree
Senior Workaround Developer

Django REST Framework и вложенные ресурсы (url)?

Хочу сделать API со следующей структурой:
/user                        - данные пользователя
/user/companies              - список компаний пользователя
/user/companies/1            - конкретная компания
/user/companies/1/contacts   - список контактов компании
/user/companies/1/contacts/2 - конкретный контакт


Хочу всё сделать на ViewSet, но сталкиваюсь с тем, что приходиться переопределять методы, чтобы "пробросить" company_id.
class PhotosViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.CompanyPhotoSerializer
    queryset = models.CompanyPhoto.objects.all()
    permission_classes = [permissions.IsOwnerOrReadOnly]

    def list(self, request, *args, **kwargs):
        queryset = self.queryset.filter(company_id=kwargs['company_id'])
        serializer = self.serializer_class(queryset, many=True)
        return response.Response(serializer.data)

    def retrieve(self, request, *args, **kwargs):
        queryset = self.queryset.filter(company_id=kwargs['company_id'])\
            .get(id=kwargs['pk'])
        serializer = self.serializer_class(queryset)
        return response.Response(serializer.data)


Соответственно мне так придеться переписать большинство вьюсетов и их методов. А тут уж проще обычные вьюхи использовать. Подскажите как это можно сделать элегантнее? Рассмотрю все варианты, включая CBV и так далее.

UPD:
Вычитал про lookup_url_kwarg в Generic views, но жду ещё варианты.
  • Вопрос задан
  • 2299 просмотров
Решения вопроса 1
idegree
@idegree Автор вопроса
Senior Workaround Developer
Счастье привалило в виде переопределения метода get_queryset, так вьюсет отрабатывает как надо:
class PhotosViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.CompanyPhotoSerializer
    permission_classes = [permissions.IsOwnerOrReadOnly]

    def get_queryset(self):
        company = self.kwargs.get('company_id')
        photos = models.CompanyPhoto.objects.filter(company_id=company)
        return photos

Ещё проще жить когда так:
class ParentIDMixin:
    parent_field = ''
    model = None

    def get_queryset(self, *args, **kwargs):
        queryset = self.model.objects.filter(**self._get_filter_key())
        return queryset

    def _get_filter_key(self):
        parent_id = self.kwargs.get(self.parent_field)
        return {self.parent_field: parent_id}


class PhotosViewSet(ParentIDMixin, viewsets.ModelViewSet):
    serializer_class = serializers.CompanyPhotoSerializer
    permission_classes = [permissions.IsOwnerOrReadOnly]
    model = models.CompanyPhoto
    parent_field = 'company_id'
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@artinnok
бекенд-программист
Почитайте на тему вложенных урлов:
https://stackoverflow.com/questions/20951419/what-...
https://softwareengineering.stackexchange.com/ques...

На мой взгляд, вложенные урлы тяжелее поддерживать, поэтому стараюсь держать структуру максимально плоской.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы