Проектирование 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/.