Проектирование DRF API: лучший способ создания представлений для вошедшего пользователя

Я работаю над приложением DRF + React, которое позволяет пользователям маркировать медицинские данные. Нужно ваше мнение о дизайне моего API

Здесь есть 3 модели: Пользователь, Аннотация и IC (независимый компонент). Каждый пользователь может сделать только одну аннотацию для каждой ИС.

В настоящее время я сделал отдельное представление с неявной подстановкой пользователей. GET дает мне существующую аннотацию для пользователя или пустой JSON, если она не существует. POST позволяет мне создать/обновить аннотацию для пользователя. URL имеет вид /api/user-annotation-by-ic/1

class UserAnnotationByIcView(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = UserAnnotationSerializer

    def get(self, request, ic_id):
        try:
            obj = Annotation.objects.get(ic=ic_id, user=request.user)
            serializer = self.serializer_class(obj)
            return Response(serializer.data)
        except ObjectDoesNotExist:
            return Response({})

    def post(self, request, ic_id):
        create = False
        data = request.data
        data['ic'] = ic_id
        context = {
            'request': self.request,
        }
        try:
            obj = Annotation.objects.get(ic=ic_id, user=request.user)
            serializer = self.serializer_class(obj, data=data, context=context)
        except ObjectDoesNotExist:
            serializer = self.serializer_class(data=data, context=context)
            create = True

        serializer.is_valid(raise_exception=True)
        serializer.save()
        if create:
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.data)

Во всех руководствах по DRF я вижу ViewSet CRUD представления с функцией фильтрации. Следуя этому подходу, я мог бы использовать URL типа /api/annotations?user=1&ic=1. В целях безопасности я должен буду проверить, что предоставленный пользователь соответствует зарегистрированному пользователю.

Так какой же подход лучше? Каковы лучшие практики?

Заранее спасибо

Ни один из подходов не является обязательно "правильным" или "неправильным", поскольку в конечном итоге все зависит от того, что лучше всего подходит для вашего приложения и команды разработчиков.

Однако, по моему опыту, использование ресурсно-ориентированного подхода к проектированию API более удобно для обслуживания и расширения в долгосрочной перспективе. Подход, основанный на ресурсах, также сделает API более "REST-полным"

Под "ресурсно-ориентированным" я подразумеваю, что конечные точки API будут структурированы на основе ресурсов, или сущностей/объектов. Например, в вашем приложении могут быть отдельные конечные точки API для User, Annotation и IC. Маршруты URL для этих конечных точек могут быть следующими:

  • Пользователь: /api/users
  • Аннотация: /api/annotations
  • IC: /api/ics

Как вы упомянули, сущность Annotation можно запросить, используя подход, подобный следующему:

api/annotations?user=1&ic=1

Такая структура URL позволяет конечной точке быть более универсальной и многократно используемой. Она также может быть легко расширена для добавления дополнительной фильтрации и функциональности для будущего использования.

С другой стороны, структурирование конечной точки API Annotation как /api/user-annotation-by-ic/1 по-прежнему эффективно, но оно менее универсально и пригодно для повторного использования. Эта конечная точка кажется очень специфичной, и поэтому ее можно использовать только для одной цели. Когда потребуется новая или другая функциональность, ее, скорее всего, нужно будет поместить в другую конечную точку. Это приведет к тому, что со временем потребуется поддерживать большее количество конечных точек

Наконец, что касается моего замечания о том, что нужно быть более "REST-ful", в этой статье содержится полезная информация о разработке REST API вокруг ресурсов: https://restfulapi.net/rest-api-design-tutorial-with-example/.

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