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

How to combine mutations to create or login user in django-graphql-jwt?

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

现在我有:

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

我尝试了不同的变体,但似乎我不完全理解图表的工作流程or\and魔法Graphene有什么作用(它的文档没有提供信息)。

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

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

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. 我没有找到如何从突变中调用突变(如何从class GetOrCreateUser中调用class CreateUser,所以我决定将CreateUser整合到GetOrCreateUser).

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

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

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

完整代码如下:

# 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 字段来定义状态。如果为空,则创建用户,如果有内容,则用户存在并刚刚登录。

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

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

这里是来自 docs 的注册突变:

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

它已经 return 来自 django-graphql-jwt 的令牌和刷新令牌。

您可以使用登录,来自 docs:

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

PS: 我是作者