Доступ к объекту hyperlinkedRelatedField из класса разрешений - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь сделать API-интерфейс из чего-то вроде Reddit.Я хочу убедиться, что тот, кто создает пост (модель Post) в определенном субреддите, является членом этого субреддита (модель субреддита - Sub).Вот мое последнее усилие, которое работает, но кажется довольно небрежным, и сериализатор для некоторого контекста.

Пост permissions.py

class IsMemberOfSubOrReadOnly(BasePermission):
    def has_permission(self, request, view):

        if request.method in permissions.SAFE_METHODS:
            return True

        elif request.data:
            # prevent creation unless user is member of the sub
            post_sub_pk = get_pk_from_link(request.data['sub'])
            user = request.user
            user_sub_pks = [sub.pk for sub in user.subs.all()]
            if not (post_sub_pk in user_sub_pks):
                return False

    return True

Post serializers.py

from .models import Post
from redditors.models import User
from subs.models import Sub

class PostSerializer(serializers.HyperlinkedModelSerializer):

    poster = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        #queryset=User.objects.all(),
        read_only=True
    )

    sub = serializers.HyperlinkedRelatedField(
        view_name='sub-detail',
        queryset=Sub.objects.all()
    )

    class Meta:
        model = Post
        fields = ('url', 'id', 'created', 'updated', 'title', 'body',
                    'upvotes', 'sub', 'poster')

Проблема с этим подходом состоит в том, что, поскольку 'sub' является гиперссылкойRelatedField на сериализаторе Post, я получаю обратноиз request.data['sub'] - просто URL-адрес гиперссылки на строку.Затем у меня есть функция get_pk_from_link, которая использует регулярные выражения для чтения pk с конца URL.Затем я могу использовать это, чтобы получить нужную модель и проверить вещи.Было бы неплохо, если бы существовал более прямой способ доступа к модели Sub, участвующей в запросе.

Я попытался найти поля доступных аргументов и не могу найтиспособ добраться до объекта Sub напрямую.Есть ли способ получить доступ к объекту модели Sub через URL-адрес гиперссылки?

Я также решил эту проблему, просто используя валидатор поля сериализатора (не показан выше), но мне интересно знать, как это сделать также.Может быть, это просто плохая идея, и если так, пожалуйста, дайте мне знать, почему.

1 Ответ

0 голосов
/ 14 октября 2018

Вы правы, разбор URL - это не тот путь.Поскольку вы хотите выполнить проверку разрешений перед созданием объекта Post, я подозреваю, что вы также не можете использовать разрешения уровня объекта , поскольку DRF не вызывает get_object в CreateAPIView (поскольку объектеще не существует в базе данных).

Учитывая, что это проверка "бизнес-логики", более простым подходом было бы вообще не иметь этот класс разрешений и выполнить проверку в вашем perform_create хук на ваш взгляд (я задавал аналогичный вопрос об этом ранее):

from rest_framework.exceptions import PermissionDenied

# assuming you have a view class like this one for creating Post objects
class PostList(generics.CreateApiView):
    # ... other view stuff

    def perform_create(self, serializer):
        sub = serializer.get('sub') # serializer is already validated so the sub object exists
        if not self.request.user.subs.filter(pk=sub.pk).exists():
            raise PermissionDenied(detail='Sorry, you are not a member of this sub.')
        serializer.save()

Это избавляет вас от необходимости выполнять этот анализ URL, как это должно дать вам сериализаторSub объект напрямую.

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