Python 从权限类访问hyperlinkedRelatedField对象
我正在尝试制作一个类似reddit的api后端。我想确保在特定子Reddit中创建帖子(modelPython 从权限类访问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
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()