Реализация REST API с помощью Django
Это моя модель Django:
class M(models.Model):
a = models.IntegerField()
b = models.IntegerField()
Это сериализатор:
class MSerializer(ModelSerializer):
class Meta:
model = M
fields = ['a', 'b']
Я хотел бы иметь возможность реализовать эти REST API:
127.0.0.1:8000/m/
(GET список всех элементов, POST новый элемент)127.0.0.1:8000/m/:id/
(GET детали элемента с idid
)127.0.0.1:8000/n/:a/m/
(ПОЛУЧИТЬ все элементы с определенным полемa
)
На данный момент это представление и урлы, которые я реализовал:
class MViewSet(ModelViewSet):
queryset = M.objects.all()
serializer_class = MSerializer
router = DefaultRouter()
router.register(r'm', MViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Однако в этом случае третий вариант использования не работает. Как я могу изменить свой код, чтобы третий случай работал? Я бы предпочел использовать как можно меньше строк кода (т.е. я хотел бы использовать некоторые встроенные функции Django).
Поскольку похоже, что вам нужна 3-я конечная точка в другом корне (возможно, в имени другого приложения n
), я реализую ее как отдельное представление API, а не как действие в наборе представлений (хотя оба варианта возможны)
class FilteredMListView(ListAPIView):
serializer_class = MSerializer
def get_queryset(self):
return M.objects.filter(a=self.kwargs["a"])
Затем зарегистрируйте его на маршрутизаторе, используя:
urlpatterns = [
path("n/<str:a>/m/", FilteredMListView.as_view())
]
Для вашего третьего случая я бы использовал ListAPIView
, переопределив метод get_queryset
для фильтрации по переданному значению для a
. Идея заключается в том, что при вызове метода get_queryset
, а также при использовании любого другого фильтра, который вы захотите реализовать, условие для a
всегда присутствует. Поскольку значение для a
будет находиться в url, оно обязательно, и вы всегда имеете его в kwargs представления. Это будет выглядеть следующим образом:
urls.py
router = DefaultRouter()
router.register(r'm', MViewSet)
urlpatterns = [
path('', include(router.urls)),
path('<a>/m', AValuesListApiView.as_view()
]
views.py
class AValuesListApiView(generics.ListAPIView):
queryset = M.objects.all()
serializer_class = MSerializer
def get_queryset(self):
return super().get_queryset().filter(score=self.kwargs["score"])