Python 如何隐藏/排除graphene_django wrt请求实体中外键的某些字段?

Python 如何隐藏/排除graphene_django wrt请求实体中外键的某些字段?,python,django,graphql,graphene-django,Python,Django,Graphql,Graphene Django,我已经阅读了关于如何在这些链接中排除(隐藏)django和graphene_django中的某些字段的内容: 等等 假设我们有下面的Post模型,它具有用户模型的外键 apps/posts/models.py 来自django.db导入模型的 从apps.users.models导入用户 班级职务(models.Model): author=models.ForeignKey( 用户, 在_delete=models.CASCADE上, 空=假 ) 已创建\u at=models.Dat

我已经阅读了关于如何在这些链接中排除(隐藏)django和graphene_django中的某些字段的内容:

  • 等等
假设我们有下面的
Post
模型,它具有
用户
模型的外键

apps/posts/models.py

来自django.db导入模型的

从apps.users.models导入用户
班级职务(models.Model):
author=models.ForeignKey(
用户,
在_delete=models.CASCADE上,
空=假
)
已创建\u at=models.DateTimeField(
auto\u now\u add=True,
)
title=models.TextField(
null=False,
最大长度=100,
)
content=models.TextField(
null=False,
)
定义(自我):
返回自己的标题
apps/users/models.py

来自django.db导入模型的

从django.contrib.auth.models导入AbstractUser
类用户(AbstractUser,models.Model):
电话号码=models.CharField(
空白=真,
空=真,
默认值=”,
最大长度=10,
详细名称=“电话号码”,
)
avatar=models.ImageField(
空=真,
上传_到class='static',
)
USERNAME\u FIELD=“USERNAME”
电子邮件\u FIELD=“电子邮件”
定义(自我):
返回self.username
我尝试了以下方法,但效果不理想:

apps/posts/schema.py

导入石墨烯
从graphene导入突变,InputObjectType,ObjectType
从graphene_django.types导入djangObjectType
从。模型导入后
类PostType(DjangObjectType):
类元:
型号=员额
排除_字段=[
“创建于”,成功了
“author.password”,我试图隐藏外键字段的方式
]
类查询(对象类型):
posts=石墨烯(
PostType
)
def解析_帖子(自我、信息):
#TODO:分页
return Post.objects.all()
屏幕截图:


如何在graphql模型类型中隐藏它的某些字段(如上例中的作者密码)?

这仅用于在解析查询字段之前检查权限。(因此,不是对原始问题的回答)

像这样的东西会有用的


def permission_check_my_field(func):
    @wraps(func)
    def wrapper(self,info,**kwargs):
        user=info.context.user
        if (......) # permit condition here
           return func(self, info,**kwargs)
        else:
            return None
    return wrapper

class  Query(graphene.ObjectType):
    my_field = graphene.Field(...) # or graphene.List or .....
    
    @permission_check_my_field
    def resolve_my_field(......)
      # do your normal work

更新

如果用户数据足以检查字段是否可访问(如)。但是,如果需要检查用户是否已被授予访问该字段的某些权限,则需要执行以下操作:


def permission_check_in_query(perm):
    def wrapped_decorator(func):
        @wraps(func)
        def wrapper(self,info,**kwargs):
            user=info.context.user
            if user.has_perm(perm) # check if the user has privilege
                return func(self, info,**kwargs)
            else:
                return None 
                # All fields are not nullable, so  `return None' might throw error. You can pass `what you need to return` in decorator argument and use it here , to avoid this.   
        return wrapper
    return wrapped_decorator

class  Query(graphene.ObjectType):
    my_field = graphene.Field(...) # or graphene.List or .....
    
    @permission_check_in_query('model.access_my_field') # your permission code 
    # learn django permissions if you are not sure what it is
    # doesn't have to be django_permission, can be any argument like 'is_it_a_superuser' that you will use to check user privilege. Modify decorator code accordingly
    def resolve_my_field(......)
      # do your normal work

这样,您就可以对任何字段和任何权限进行重用。只需将decorator
@permission\u check\u in\u query(您的参数)
添加到任何需要在解析之前进行权限检查的字段上方


TLDR:这个答案与API接受和返回的数据类型类似。它只提供可重用性和权限检查。

从评论中,我了解到您有一个
用户类型

您可以使用meta as中的排除选项

class UserType(DjangoObjectType):
    class Meta:
        model = User
        exclude = ('password',)
类用户类型(DjangObjectType):
类元:
模型=用户
排除=('password',)
更新 您还可以使用自定义解析器检查请求的实体

class UserType(DjangoObjectType):
    password = graphene.String()

    def resolve_password(self, info):
        requested_user = info.context.user
        if requested_user.email in ['admin@test.com', 'ceo@test.com']:
            return self.password
        return None

    class Meta:
        model = User
        fields = '__all__'
类用户类型(DjangObjectType):
密码=graphene.String()
def解析_密码(自我、信息):
请求的用户=info.context.user
如有要求,请在['admin@test.com', 'ceo@test.com']:
返回自我密码
一无所获
类元:
模型=用户

fields='\uuuu all\uuuuu'
如何创建一个
AuthorType(djangObjectType)
来排除字段
password
,并在
PostType
中使用该类型和
author=graphene.field(AuthorType)
@SagarAdhikari您的意思是将其添加到PostType元类中吗?不,元类上方,(类似于类变量)@SagarAdhikari你能给我举个例子吗?想象一下您基于不同权限执行此操作的情况。例如,超级用户可以看到电子邮件字段,但普通用户看不到。GraphQL API需要事先指定可以从服务器获取/发布的数据类型。所以,据我所知,这是违反graphql标准的。但是,您可以检查权限,并向普通用户发送消息“此字段不可访问”,而不是发送数据。我已经为这个问题添加了奖励,如果您能指导我怎么做并更新您的答案,我将不胜感激。我给出的这个答案与其他答案类似,除了返回“PermissionDenied”之外,我刚刚添加了decorators以实现可重用性。您可以创建一个接受参数的decorator,即您的权限代码(这里我使用了无参数decorator),这将使其可用于任何字段。现在,我用参数更新了docorator,您可以在其中传递权限和检查。现在一切正常:)我不想为所有用户排除它。正如我在帖子中解释的,我想对具有不同权限的特定用户隐藏它。哦。。我懂了。好了,没有现成的方法来进行这种权限检查。你是说它有严重的安全问题?如果你能告诉我,我将不胜感激。我不认为这是一个安全问题。我认为这是“这个功能还没有在graphene中实现”,那么Facebook、Instagram和其他人是如何使用它的呢?你是说他们为此尝试了不同的API?比如restful api?