Как правильно сопоставить API с представлениями в Django - PullRequest
0 голосов
/ 21 сентября 2018

Мой вопрос сводится к одной из лучших практик для REST и Views в Django.Я переделываю REST API для моего текущего проекта, и это включает в себя доработку наших Views (Controller в традиционном MVC).В настоящее время все проходит через POST-запросы, даже вещи, которые должны быть простыми GET.

С точки зрения отдыха, список всех заданий должен быть возвращен с URL-адресом:

api / jobs /

и одно задание (с идентификатором 1) должно быть получено с помощью:

api / jobs / 1

и, наконец, это должно вернуть все задачи, которые являются частью задания 1

API / jobs / 1 / tasks /

Это философия, которую я использую дляновая система, но я разрываюсь на реализацию.Если оба из них получат свое собственное представление в Django, или одно представление будет обрабатывать оба.

В настоящее время я использую одно представление, куда все соответствующие URL-адреса направляются к нему, с такой логикой;

def get(self, request, id=None, task_id=None):

    if id is None:
        return Job.objects.all()  # This will be the LIST'
    if task_id is not None:
        return Job.objects.get(id=id).task_set.all()
    return Job.objects.get(id=id)

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

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Я не думаю, что вы должны включать все это в одно представление.Я бы использовал два ModelViewSets и структурировал их URL, как показано ниже:

views.py

class JobViewSet(ModelViewSet):
    serializer_class = JobSerializer
    queryset = Job.objects.all()

class TaskViewSet(ModelViewSet):
    serializer_class = TaskSerializer
    queryset = Task.objects.all()

    def get_queryset(self, request, *args, **kwargs):
        # Override get_queryset to allow filtering by `job_id` url kwarg.
        qs = self.queryset
        if kwargs.get('job_id'):
            job = Job.objects.get(pk=kwargs.get('job_id'))
            qs = qs.filter(job=job)
        return qs

urls.py

urlpatterns = [
    url(
        r'^api/jobs/$', 
        JobViewSet.as_view({'get': 'list', 'post': 'create'}
    ),
    url(
        r'^api/jobs/(?P<pk>\d+)/$', 
        JobViewSet.as_view({'get': 'retrieve', 'patch': 'update', 'patch': 'partial_update', 'delete': 'destroy'}
    ),
    url(
        r'^api/jobs/(?P<job_id>\d+)/tasks/$', 
        TaskViewSet.as_view({'get': 'list', 'post': 'create'}
    ),
    url(
        r'^api/jobs/(?P<job_id>\d+)/tasks/(?P<pk>\d+)/$', 
        TaskViewSet.as_view({'get': 'retrieve', 'patch': 'update', 'patch': 'partial_update', 'delete': 'destroy'}
    ),
]

Я избегал использования Rest FrameworkМаршрутизаторы, но они, по сути, генерируют маршруты, аналогичные этим для отдельных наборов запросов, а вложенные наборы запросов усложняются с помощью маршрутизаторов.Вы можете заметить, что ваши маршруты ожидают, что аргумент ключевого слова pk для ViewSets получит один экземпляр объекта, это значение поиска по умолчанию для ModelViewSets.Как только мы вложим конечную точку /tasks/ ниже конечной точки /jobs/, нам нужно изменить аргумент ключевого слова pk на jobs_id, чтобы представление не использовало его в качестве значения поиска по умолчанию для задач.jobs_id используется в пользовательском методе get_queryset для соответствующей фильтрации.

0 голосов
/ 21 сентября 2018

Существует Rest Framework для Django, который предоставляет остальные виды, маршрутизаторы, сериализаторы и так далее.Вы должны смотреть в первую очередь на Viewsets и маршрутизаторы |Rest Framework , который именно то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...