Делюсь опытом в описанных технологиях. Блог в первую очередь выполняет роль памяток для меня самого.

Получение аргументов URL в сериализаторах Django REST Framework

2 комментария

Небольшая заметка о том, как в ClassBasedView Django REST Framework получить значение параметра из URL.

Допустим, наши URL сконфигурированы таким образом:

urls.py
from django.conf.urls import url

from .api import ArticleListCreateView
from .api import ArticleDetailView
from .api import ArticleCommentListCreateView

urlpatterns = [
    url(r'^article/$', ArticleListCreateView.as_view()),
    url(r'^article/((\d+))/$', ArticleDetailView.as_view()),
    url(r'^article/((\d+))/comment/$', ArticleCommentListCreateView.as_view()),
]

Делать какую-либо работу для вида ArticleDetailView не приходится - достаточно создать класс, унаследованный от RetrieveUpdateDestroyAPIView.

Получить доступ к параметру pk в виде не проблема, достаточно переопределить метод get_queryset(), например, так:

article.comment.api.py
from rest_framework.generics import RetrieveUpdateDestroyAPIView

from article.models import Article
from .models import ArticleComment


class ArticleCommentListCreateView(RetrieveUpdateDestroyAPIView):

    model = ArticleComment

    # Возвращаем только комментарии к указанной статье
    def get_queryset(self):
        return ArticleComment.objects.filter(article=self.kwargs['pk])

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return ArticleCommentReadSerializer
        return ArticleCommentWriteSerializer

А вот получить в сериализаторе значение параметра pk можно не вполне очевидным способом:

serializers.py
from django.shortcuts import get_object_or_404
from rest_framework import serializers

from .models import ArticleComment
from article.models import Article

# ArticleReadSerializer не описан из-за своей простоты

class ArticleCommentWriteSerializer(serializers.ModelSerializer):

    article = serializers.PrimaryKeyRelatedField(
        queryset=Article.objects.all(),
        default=None
    )

    # Заменяем валидатор поля article таким образом, чтобы всегда
    # подставлялось значение из URL
    def validate_article(self, value):
        # Кто бы мог подумать???
        article_id = self.context['view'].kwargs['pk']
        return get_object_or_404(Article, pk=article_id)

    class Meta:
        model = ArticleComment

2 комментария :

  1. Максим, спасибо вам огромное!!!!!!! Как вы додумались до view? Ведь в self ее не видно?

    ОтветитьУдалить
  2. беру свои слова обратно - видно) но перекинуть мостик дальше - это очень сильно, ещё раз спасибо

    ОтветитьУдалить