Короткий ответ
URL-версионирование (/api/v1/...) проще в реализации, кэшировании и отладке, так как версия видна прямо в адресе; версионирование через заголовок (Accept: application/vnd.myapp.v2+json или X-API-Version) держит URL чистым, но сложнее для отладки, логирования и кэширующих прокси, которые обычно не учитывают такие заголовки в ключе кэша.
Как это работает подробнее
DRF поддерживает несколько встроенных схем версионирования через DEFAULT_VERSIONING_CLASS: URLPathVersioning, NamespaceVersioning, AcceptHeaderVersioning, HostNameVersioning. Выбранная схема определяет, как request.version извлекается из запроса, и это значение можно использовать в сериализаторах/view для выбора логики.
Пример кода
example.py
from django.urls import path
from rest_framework.response import Response
from rest_framework.views import APIView
class OrderListView(APIView):
def get(self, request):
return Response({"version": request.version})
urlpatterns = [
path("api/<str:version>/orders/", OrderListView.as_view()),
]Что использовать на практике
- Практика. URL-версионирование — самый распространённый и предсказуемый вариант для публичных API: его проще документировать, тестировать через curl, кэшировать на уровне CDN по пути. Versioning через заголовок иногда выбирают для внутренних API, где важно не «размножать» пути, но тогда нужно убедиться, что вся инфраструктура (прокси, логирование, мониторинг) корректно учитывает этот заголовок.
Подводные камни
- Риск. Вводят версионирование API только «задним числом», когда уже накопились клиенты на v1 без возможности безопасно эволюционировать контракт; смешивают схемы (часть эндпоинтов версионируют по URL, часть — по заголовку) без единой политики, что усложняет поддержку.