如何结合突变在 django-graphql-jwt 中创建或登录用户?

Posted

技术标签:

【中文标题】如何结合突变在 django-graphql-jwt 中创建或登录用户?【英文标题】:How to combine mutations to create or login user in django-graphql-jwt? 【发布时间】:2018-08-22 10:55:49 【问题描述】:

我使用 VueJS 和 Django + django-graphql-jwt(返回令牌)。我想使用电子邮件\密码字段进行注册和登录。在服务器上,我想检查提供的电子邮件是否已经存在 -> 使用 django-graphql-jwt 的突变 token_auth = graphql_jwt.ObtainJSONWebToken.Field() 返回令牌 + 消息,否则 -> 使用提供的电子邮件和密码创建一个新用户并返回此用户 + 消息。

现在我有:

# schema.py

import graphene
import graphql_jwt

from django.contrib.auth import get_user_model
from graphene_django import DjangoObjectType


class UserType(DjangoObjectType):
    class Meta:
        model = get_user_model()


class CreateUser(graphene.Mutation):
    user = graphene.Field(UserType)

    class Arguments:
        password = graphene.String(required=True)
        email = graphene.String(required=True)

    def mutate(self, info, password, email):
        user = get_user_model()(
            username=email.split('@')[0],
            email=email,
        )
        user.set_password(password)
        user.save()

        return CreateUser(user=user)

# Want to combine two mutations here
class GetOrCreateUser(graphene.Mutation):
    user = graphene.Field(UserType)

    class Arguments:
        password = graphene.String(required=True)
        email = graphene.String(required=True)

    def mutate(self, info, password, email):
        # Return token
        if get_user_model().objects.filter(email=email).exists():
            # Just an idea, what I want to get here (to be returned to VueJS)
            return 'token': graphql_jwt.ObtainJSONWebToken.Field(), 'msg': 'Token Generated'

        # Create new user
        else:
            user = CreateUser(???)
            return 'user': user, 'msg': 'User is Created'


class Mutation(graphene.ObjectType):
    create_user = CreateUser.Field()
    get_or_create_user = GetOrCreateUser.Field()

我尝试了不同的变体,但似乎我不完全了解图形的工作流程或\以及Graphene 的魔力(其文档没有提供信息)。

谁能告诉我,我如何在 if\else 块中重复使用已创建的代码(CreateUser 类和graphql_jwt.ObtainJSONWebToken.Field())?

【问题讨论】:

【参考方案1】:

您可以创建一个函数并在两个突变中使用它:

def get_or_create_user(password, email):
    if get_user_model().objects.filter(email=email).exists():
        return ('user or token or other data that you need in'
                'mutation, this is not mutation return value')
               # 'token': graphql_jwt.ObtainJSONWebToken.Field(),
               # 'msg': 'Token Generated'

    # Create new user
    else:
        user = get_user_model()(
            username=email.split('@')[0],
            email=email,
        )
        user.set_password(password)
        user.save()

        return ('user or token or other data that you need in'
                'mutation, this is not mutation return value')
               # 'user': user,
               # 'msg': 'User is Created'

【讨论】:

它不会像石墨烯那样工作。 1)graphql_jwt.ObtainJSONWebToken.Field() 不返回值(不返回字符串),它返回对象。 2)据我了解,返回项目的类型必须与class GetOrCreateUser(graphene.Mutation):下声明的相同,但我不知道dict应该使用哪种类型。 @TitanFighter 我刚刚复制了你的代码。这个函数的目的是 - 结合你的两个突变的 if/else 逻辑......【参考方案2】:

    我没有找到如何从突变中调用突变(如何从class GetOrCreateUser 调用class CreateUser,因此我决定将CreateUser 整合到GetOrCreateUser

    李>

    我没有找到,如何通过类似代码调用graphql_jwt(示例取自graphene doc)

    schema = graphene.Schema(...)
    result = schema.execute(' name ')
    

    所以我决定直接通过 Python 而不是 Python\GraphQL 获取令牌。

以下是完整代码:

# schema.py (the root one)
import graphene
import graphql_jwt
import apps.users.schema


class Query(apps.users.schema.Query, graphene.ObjectType):
    pass


class Mutation(apps.users.schema.Mutation, graphene.ObjectType):
    verify_token = graphql_jwt.Verify.Field()
    refresh_token = graphql_jwt.Refresh.Field()


schema = graphene.Schema(query=Query, mutation=Mutation)

# users/schema.py
import graphene

from django.contrib.auth import get_user_model
from graphene_django import DjangoObjectType
from graphql_jwt.shortcuts import get_token


class UserType(DjangoObjectType):
    class Meta:
        model = get_user_model()


class GetOrCreateUser(graphene.Mutation):
    """
    mutation 
      getOrCreateUser(email: "test@domain.com", password: "YourPass") 
        token
        user 
          id
          email
          isActive
        
      
    
    """

    user = graphene.Field(UserType)
    token = graphene.String()

    class Arguments:
        password = graphene.String(required=True)
        email = graphene.String(required=True)

    def mutate(self, info, password, email):
        token = ''

        # Return token
        if get_user_model().objects.filter(email=email).exists():
            user = get_user_model().objects.get(email=email)
            token = get_token(user)

        # Create new user
        else:
            user = get_user_model()(
                username=email.split('@')[0],
                email=email,
            )
            user.set_password(password)
            user.save()

        return GetOrCreateUser(user=user, token=token)


class Query(graphene.ObjectType):
    users = graphene.List(UserType)

    def resolve_users(self, info):
        return get_user_model().objects.all()

FrontEnd 可以通过检查token 字段来定义状态。如果为空,则创建用户,如果有内容,则用户存在并刚刚登录。

【讨论】:

【参考方案3】:

django-graphql-auth 完全符合您的要求。

它扩展了 django-graphql-jwt 以处理所有与用户帐户相关的操作。

这是来自docs的注册突变:

mutation 
  register(
    email:"skywalker@email.com",
    username:"skywalker",
    password1: "supersecretpassword",
    password2:"supersecretpassword"
  ) 
    success,
    errors,
    token,
    refreshToken
  

它已经从 django-graphql-jwt 返回了令牌和刷新令牌。

比你可以用来登录的,来自docs:

mutation 
  tokenAuth(
    # username or email
    email: "skywalker@email.com"
    password: "supersecretpassword"
  ) 
    success,
    errors,
    token,
    refreshToken,
    unarchiving,
    user 
      id,
      username
    
  

PS:我是作者

【讨论】:

以上是关于如何结合突变在 django-graphql-jwt 中创建或登录用户?的主要内容,如果未能解决你的问题,请参考以下文章

CQRS 命令和 GraphQL 突变

将 AWS Appsync 与 AWS Neptune 结合使用

GraphQL - 如何在查询多个突变期间检索先前突变的 id

如何在 GraphQL 中执行突变?

如何在突变 graphQL Playground 中传递变量?

多重突变:如何让第一个突变将 ID 传递给第二个突变