Реализация 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 детали элемента с id id)
  • 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"])
Вернуться на верх