python - 从权限类访问 hyperlinkedRelatedField 对象

标签 python django django-rest-framework

我正在尝试为 reddit 之类的东西制作一个 api 后端。我想确保在特定 subreddit 中创建帖子(模型 Post)的人都是该 subreddit 的成员(subreddit 模型是 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

发布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' 是 Post 序列化器上的 hyperlinkedRelatedField 我从 request.data['sub'] 返回的只是字符串超链接 url。然后,我有一个函数 get_pk_from_link,它使用正则表达式读取 url 末尾的 pk。然后我可以用它来获取我想要的实际模型并检查内容。如果有一种更直接的方法来访问请求中涉及的 Sub 模型,那就太好了。

我尝试搜索可用参数的字段,但找不到直接访问 Sub 对象的方法。有没有办法通过超链接 url 访问 Sub 模型对象?

我还通过使用序列化器字段验证器(上面未显示)解决了这个问题,但我也有兴趣知道如何这样做。也许这只是一个坏主意,如果是这样,请告诉我原因。

最佳答案

你是对的,解析 url 不是正确的方法。由于您想在创建 Post 对象之前执行权限检查,我怀疑您不能使用 object level permissions或者,因为 DRF 不会在 CreateAPIView 中调用 get_object(因为数据库中尚不存在该对象)。

考虑到这是一个“业务逻辑”检查,更简单的方法是根本没有该权限类并在 perform_create 中执行检查。在你看来,钩子(Hook)(我之前曾向similar question询问过这个问题):

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 对象。

关于python - 从权限类访问 hyperlinkedRelatedField 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52783850/

相关文章:

python - 使用 URL 将参数传递给 CGI 程序 (python)

python - 为什么我的脚本在删除数百万个文件时会定期卡住?

django - 在 django 模板中使用模型字段渲染 ckeditor 小部件

django rest framework - 我应该为通用过滤器提供什么 URL?

javascript - 将子类别作为数组对象中的数组

android - 获取 token 身份验证 View 时出现 Django REST HTTP 400 错误

python - 如何判断 VS Code 使用的 Python 格式化程序的版本?

python - 为什么TensorFlow训练过程中变量值没有改变?

python - 从 Linux 上的 Web 服务器在 Windows 上运行任务的最佳方式

django - Django 的管理面板只是临时脚手架吗?