Настройка ответа от мутации с помощью django-graphql-auth с graphene
Я использую django-graphql-auth и graphene в своем проекте django. Библиотека django-graphql-auth хороша, но ей немного не хватает документации и примеров настройки. Я уже отправил этот вопрос туда, но репо, кажется, не получает большой активности в последнее время (возможно, пришло время заменить и использовать другой пакет в проекте), поэтому я попытаю счастья здесь:
большинство вопросов, связанных с настройкой, касаются входов. В моем случае я хотел бы изменить вывод мутации Register, поскольку мне нужен id пользователя, созданного в ответе
На данный момент мне удалось создать новую пользовательскую мутацию, которая наследует регистр, поэтому я могу добавить логику для захвата созданного пользователя:
class RegisterCustom(mutations.Register):
response = graphene.Field(RegisterResponseType)
@classmethod
def mutate(cls, *args, **kwargs):
try:
res = super().mutate(*args, **kwargs)
if res.success:
user = get_user_model().objects.order_by('-date_joined')[:1]
return RegisterCustom(success=True, error="", user_id=user[0]['id'])
except Exception:
raise Exception(res.errors)
Однако отдача не та, которую я ожидаю
{
"errors": [
{
"message": "None",
"locations": [
{
"line": 472,
"column": 5
}
],
"path": [
"registerCustom"
]
}
],
"data": {
"registerCustom": null
}
}
Если я добавлю print прямо перед return, скажем, print(user[0]['id']), я увижу, что выводится id пользователя. Я предполагаю, что в этой строке: res = super().mutate(*args, **kwargs)
, вызывая метод mutate на Register, я уже обречен получить ответ от родительского метода, что бы я ни делал дальше.
Я также попробовал другой подход. Этот основан на примере из graphene docs :
class RegisterCustom(mutations.Register):
Output = RegisterResponseType
@classmethod
def mutate(cls, *args, **kwargs):
try:
res = super().mutate(*args, **kwargs)
if res.success:
user = get_user_model().objects.order_by('-date_joined')[:1]
return RegisterResponseType(sucess=True, error="", user_id=user[0]['id'])
except Exception:
raise Exception(res.errors)
Также пробовал этот способ, без успеха
class RegisterCustom(mutations.Register):
response = graphene.Field(RegisterResponseType)
@classmethod
def mutate(cls, *args, **kwargs):
try:
res = super().mutate(*args, **kwargs)
if res.success:
user = get_user_model().objects.order_by('-date_joined')[:1]
response = {'success': True, 'error': '', 'user_id': user[0]['id']}
return RegisterCustom(response=response)
except Exception:
raise Exception(res.errors)
Идеально я хочу решить это с помощью django-graphql-auth, так как у меня уже есть много функций, сделанных с его помощью, будь это хорошее решение или хак, мне все равно, так как я не буду сталкиваться с этим сценарием слишком часто. Я не хочу заменять всю логику аутентификации на данном этапе. Я думаю, что это довольно просто сделать, но отсутствие документации затрудняет это
Вы на правильном пути. Самое простое решение - объявить дополнительное целочисленное поле:
class RegisterCustom(mutations.Register):
user_id = graphene.Int()
@classmethod
def mutate(cls, *args, **kwargs):
try:
email = kwargs.get("email")
UserStatus.clean_email(email)
res = super().mutate(*args, **kwargs)
user = get_user_model().objects.filter(email=email).first()
return cls(
success=res.success,
errors=res.errors,
token=res.token,
refresh_token=res.refresh_token,
user_id=user.pk if user else None,
)
except Exception:
raise Exception(res.errors)
Вы можете, однако, вернуть RegisterResponseType
, но не забудьте также изменить тип соответствующим образом
class RegisterCustom(mutations.Register):
response = graphene.Field(RegisterResponseType)
@classmethod
def mutate(cls, *args, **kwargs):
try:
...
return cls(
success=res.success,
errors=res.errors,
token=res.token,
refresh_token=res.refresh_token,
response=response,
)
except Exception:
...
и что response
является моделью или экземпляром класса, который соответствует RegisterResponseType