我正在尝试为 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/