GraphQL: [Errno 111] Connection refused
Description
I am trying to build an API for a transportation system which has different kind of users (Driver, Customer, SystemAdmin and Authorizer). For this purpose I created an AbstractUser
and use inheritance relationship for the all of the above different users.
For adding JWT to the model, I have read the official tutorial, but whenever I want to create a new user like the following I faced to the error:
mutation {
register(
email: "new_user@email.com",
username: "new_user",
password1: "supersecretpassword",
password2: "supersecretpassword",
) {
success,
errors,
token,
refreshToken
}
}
Steps to Reproduce
- Here is my model:
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class Usermodel(AbstractUser, models.Model):
phone_no = models.CharField(
max_length=11,
blank=True,
verbose_name="Phone Number"
)
USERNAME_FIELD = "username" # e.g: "username", "email"
EMAIL_FIELD = "email" # e.g: "email", "primary_email"
def __str__(self):
return self.username
class Driver(Usermodel, models.Model):
national_id = models.CharField(
max_length=10,
blank=True,
verbose_name="National ID"
)
profile_picture = models.ImageField(
blank=True,
null=True
)
STATUS_CHOICES = [
('1', 'Free'),
('2', 'Busy')
]
driver_status = models.CharField(
max_length=1,
choices=STATUS_CHOICES
)
rating = models.FloatField(
default=-1
)
ranking = models.IntegerField(
default=-1
)
class Meta:
verbose_name = 'Driver'
verbose_name_plural = 'Drivers'
class Authorizer(Usermodel, models.Model):
class Meta:
verbose_name = 'Authorizer'
verbose_name_plural = 'Authorizers'
class Customer(Usermodel, models.Model):
class Meta:
verbose_name = 'Customer'
verbose_name_plural = 'Customers'
class Administrator(Usermodel, models.Model):
class Meta:
verbose_name='Adminsitrator'
verbose_name_plural='Administrators'
- users schema
import graphene
from graphene import Mutation, ObjectType, InputObjectType
from .models import Driver, Authorizer, Customer, Administrator
from graphene_django.types import DjangoObjectType
class DriverType(DjangoObjectType):
class Meta:
model = Driver
class AuthorizerType(DjangoObjectType):
class Meta:
model = Authorizer
class Query(ObjectType):
driver = graphene.Field(
DriverType,
id = graphene.ID()
)
authorizer = graphene.Field(
AuthorizerType,
id = graphene.ID()
)
all_drivers = graphene.List(DriverType)
all_authorizers = graphene.List(AuthorizerType)
def resolve_all_drivers(self, info, **kwargs):
return Driver.objects.all()
def resolve_driver(self, info, **kwargs):
id = kwargs.get('id')
if id is not None:
return Driver.objects.get(pk=id)
def resolve_authorizer(self, info, **kwargs):
id = kwargs.get('id')
if id is not None:
return Driver.objects.get(pk=id)
def resolve_all_authorizers(self, info, **kwargs):
return Authorizer.objects.all()
class DriverInput(InputObjectType):
first_name = graphene.String()
last_name = graphene.String()
email = graphene.String()
username = graphene.String()
phone_no = graphene.String()
national_id = graphene.String()
password = graphene.String()
class AuthorizerInput(InputObjectType):
first_name = graphene.String()
last_name = graphene.String()
email = graphene.String()
username = graphene.String()
phone_no = graphene.String()
password = graphene.String()
class CreateDriver(Mutation):
class Arguments:
driver_data = DriverInput()
driver = graphene.Field(DriverType)
def mutate(self, info, driver_data=None):
driver = Driver(
first_name=driver_data.first_name,
last_name=driver_data.last_name,
email=driver_data.email,
username=driver_data.username,
phone_no=driver_data.phone_no,
national_id=driver_data.national_id,
password=driver_data.password
)
driver.save()
return CreateDriver(
driver=driver
)
class UpdateDriver(Mutation):
class Arguments:
id = graphene.ID()
driver_data = DriverInput()
driver = graphene.Field(DriverType)
def mutate(self, info, id, driver_data=None):
#TODO: Error handling if the id not exists
driver = Driver.objects.get(pk=id)
driver.first_name = driver_data.first_name
driver.last_name = driver_data.last_name
driver.email = driver_data.email
driver.username = driver_data.username
driver.phone_no = driver_data.phone_no
driver.national_id = driver_data.national_id
driver.password = driver_data.password
driver.save()
return UpdateDriver(driver=driver)
class AuthorizerInput(InputObjectType):
first_name = graphene.String()
last_name = graphene.String()
email = graphene.String()
username = graphene.String()
phone_no = graphene.String()
password = graphene.String()
class CreateAuthorizer(Mutation):
class Arguments:
authorizer_data = AuthorizerInput()
authorizer = graphene.Field(AuthorizerInput)
def mutate(self, info, authorizer_data=None):
authorizer = Authorizer(
firstname=authorizer_data.first_name,
last_name=authorizer_data.last_name,
email=authorizer_data.email,
username=authorizer_data.username,
phone_no=authorizer_data.phone_no,
password=authorizer_data.password
)
authorizer.save()
return CreateAuthorizer(authorizer=authorizer)
class UpdateAuthorizer(Mutation):
class Arguments:
id = graphene.ID()
authorizer_data = AuthorizerInput()
authorizer = graphene.Field(AuthorizerType)
def mutate(self, info, id, authorizer_data=None):
authorizer = Authorizer.objects.get(pk=id)
authorizer.first_name = authorizer_data.first_name
authorizer.last_name = authorizer_data.last_name
authorizer.email = authorizer_data.email
authorizer.username = authorizer_data.username
authorizer.password = authorizer_data.password
authorizer.save()
return UpdateDriver(authorizer=authorizer)
class Mutations(ObjectType):
create_driver = CreateDriver.Field()
update_driver = UpdateDriver.Field()
- project schema
import graphene
from apps.users.schema import Query as user_query
from apps.users.schema import Mutations as user_mutation
from graphql_auth.schema import UserQuery, MeQuery
from graphql_auth import mutations
class AuthMutation(graphene.ObjectType):
register = mutations.Register.Field()
class Query(user_query, UserQuery, MeQuery):
pass
class Mutations(user_mutation, AuthMutation):
pass
schema = graphene.Schema(
query=Query,
mutation=Mutations
)
Expected behavior
I expect the code to run without any problem but face to the following error in actual behavior
I also have another question. As I have explained for the various kind of user and registration of them, I need different arguments. But in schema we just add register = mutations.Register.Field()
, Как я могу достичь этой цели?
Фактическое поведение
Требования
aniso8601==7.0.0
asgiref==3.2.10
Django==3.0.8
django-filter==2.3.0
django-graphql-auth==0.3.11
django-graphql-jwt==0.3.0
graphene==2.1.8
graphene-django==2.12.1
graphql-core==2.3.2
graphql-relay==2.0.1
Pillow==7.2.0
pkg-resources==0.0.0
promise==2.3
PyJWT==1.7.1
pytz==2020.1
Rx==1.6.1
singledispatch==3.4.0.3
six==1.15.0
sqlparse==0.3.1
Unidecode==1.1.1
1 ответ
Вопрос 1. Я ожидаю, что код будет работать без каких-либо проблем, но при фактическом поведении сталкиваюсь со следующей ошибкой
NB. Будет немного сложно ответить на этот вопрос, не видя, как
settings.py
настроен, но дважды проверьте, выполнили ли вы все шаги. Я тоже прошел быстрый старт, но все же пропустил несколько мест.
A: Убедитесь, что у вас есть settings.py
правильно настроен
Я столкнулся с аналогичной ошибкой "Соединение отклонено", но проблема заключалась в том, что мои настройки не были настроены должным образом.
Изменить: после дальнейшей локальной разработки и переключения с индивидуальными настройками я понял, что моя ошибка "Отказ в соединении" связана с отсутствием
EMAIL_BACKEND
настроен. Он пытался подключиться к любому SMTP-серверу, который не работал. Убедитесь, что у вас естьEMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
установите для регистрации этой функции на вашей консоли.
Вот немного сокращенная копия моего settings.py
с нуля, который я использовал, просто чтобы убедиться, что он у вас настроен правильно:
Источник: https://django-graphql-auth.readthedocs.io/en/latest/quickstart/.
NB: это немного длинновато, обязательно пролистайте его до конца
# ...
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# Package apps
"corsheaders",
"graphene_django",
"graphql_jwt.refresh_token.apps.RefreshTokenConfig",
"graphql_auth",
"django_filters",
# Created apps
"users", # or whatever the name of the app is with your custom users model
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "<project_name>.urls"
# TEMPLATES = ...
# WSGI_APPLICATION = ...
# DATABASES = ...
# Ensure that custom user is set
AUTH_USER_MODEL = "users.CustomUser"
# AUTH_PASSWORD_VALIDATORS = ...
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
# ...
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
# ...
GRAPHENE = {
"SCHEMA": "backend.schema.schema",
"MIDDLEWARE": ["graphql_jwt.middleware.JSONWebTokenMiddleware",],
}
AUTHENTICATION_BACKENDS = [
"graphql_jwt.backends.JSONWebTokenBackend",
"django.contrib.auth.backends.ModelBackend",
"graphql_auth.backends.GraphQLAuthBackend",
]
GRAPHQL_JWT = {
"JWT_VERIFY_EXPIRATION": True,
"JWT_LONG_RUNNING_REFRESH_TOKEN": True,
}
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
Вопрос 2: Как я объяснил для различных типов пользователей и их регистрации, мне нужны разные аргументы. Но в схеме мы просто добавляем register = mutations.Register.Field(), как я могу достичь этой цели?
A: TL; DR - это объясняется в разделе динамических полей документации по настройкам.
A: Прохождение
Шаг 1. Убедитесь, что в вашей пользовательской модели задано поле
Прежде чем мы подумаем об обновлении наших настроек, убедитесь, что настраиваемое поле, которое вы должны установить, существует в модели. Например, если бы я хотелluck_number
поле, я бы добавил:
class CustomUser(AbstractUser):
...
luck_number = models.IntegerField()
...
Затем вам нужно убедиться, что вы выполняете миграции, чтобы они существовали в вашей базе данных.python manage.py makemigrations
python manage.py migrate
Шаг 2: Добавить GRAPHQL_AUTH
к settings.py
В своих настройках обязательно установите:
# Rest of your settings ...
GRAPHQL_AUTH = {}
Шаг 3. Добавьте настраиваемые поля и дважды проверьте схему
Если вы хотите добавить поля для сбора при регистрации, вам необходимо добавить REGISTER_MUTATION_FIELDS
на ваш GRAPHQL_AUTH
настройки. Так что в случае добавленияluck_number
нашим register
мутация:
GRAPHQL_AUTH = {
REGISTER_MUTATION_FIELDS = {
"email": "String",
"username": "String",
"luck_number": "Int",
}
}

редактировать 1: добавление изображения
изменить 2: добавление пояснения к моей ошибке при мутации регистра