Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从权限类访问hyperlinkedRelatedField对象_Python_Django_Django Rest Framework - Fatal编程技术网

Python 从权限类访问hyperlinkedRelatedField对象

Python 从权限类访问hyperlinkedRelatedField对象,python,django,django-rest-framework,Python,Django,Django Rest Framework,我正在尝试制作一个类似reddit的api后端。我想确保在特定子Reddit中创建帖子(modelpost)的人是该子Reddit的成员(subreddit model是Sub)。下面是我的最新成果,它可以工作,但看起来相当草率,以及一些上下文的序列化程序 Post权限。py Post序列化程序.py 这种方法的问题在于,由于'sub'是Post序列化程序上的一个超链接的latedField,因此我从请求中得到的信息。data['sub']只是字符串超链接url。然后我有一个函数,get\u p

我正在尝试制作一个类似reddit的api后端。我想确保在特定子Reddit中创建帖子(model
post
)的人是该子Reddit的成员(subreddit model是
Sub
)。下面是我的最新成果,它可以工作,但看起来相当草率,以及一些上下文的序列化程序

Post权限。py

Post序列化程序.py

这种方法的问题在于,由于'sub'是
Post
序列化程序上的一个超链接的latedField,因此我从
请求中得到的信息。data['sub']
只是字符串超链接url。然后我有一个函数,
get\u pk\u from\u link
,它使用正则表达式读取url末尾的pk。然后我可以用它来抓取我想要的实际模型并进行检查。如果有更直接的方式访问请求中涉及的
Sub
模型就好了

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


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

你说得对,解析url不是一个好办法。因为您想在创建
Post
对象之前执行权限检查,所以我怀疑您不能使用这两个对象,因为DRF在
CreateAPIView
中不调用
get\u对象(因为该对象在数据库中尚不存在)

考虑到这是一个“业务逻辑”检查,一个更简单的方法是根本没有该权限类,并在您的视图中的钩子中执行检查(我在前面询问了一个关于此的问题):

这为您省去了执行url解析的麻烦,因为序列化程序应该直接将
子对象提供给您

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
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')
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()