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
}
}
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'
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()
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
)
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()
, How can I reach to this purpose?
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
N.B. It's going to be a little difficult to answer this without seeing how your
settings.py
is configured, but double-check that you went through every step. I went through the quickstart too but still missed a few spots.
settings.py
properly configuredI ran into a similar "Connection refused" error, but the issue was that my settings were not configured properly.
Edit: After further local development and toggling with individual settings, I realized that my "Connection refused error was related to not having
EMAIL_BACKEND
configured. It was trying to connect to any SMTP server that wasn't running. Make sure you haveEMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
set to log this functionality to your console.
Here's a slightly abbreviated copy of my settings.py
from a scratch project I was using, just to be sure that you have it configured correctly:
Source: django-graphql-auth quickstart.
N.B.: It's a little long, make sure to scroll all the way through
# ...
# 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"
Before we think about updating our settings, confirm that the custom field you need to set exists on the model. For example, if I wanted to have a luck_number
field, I would add:
class CustomUser(AbstractUser):
...
luck_number = models.IntegerField()
...
Then you need to make sure you run migrations so that this exists in your database.
python manage.py makemigrations
python manage.py migrate
GRAPHQL_AUTH
to settings.py
In your settings, make sure to set:
# Rest of your settings ...
GRAPHQL_AUTH = {}
If you want to add fields to collect on registration, you need to add the REGISTER_MUTATION_FIELDS
to your GRAPHQL_AUTH
settings. So in the case of adding luck_number
to our register
mutation:
GRAPHQL_AUTH = {
REGISTER_MUTATION_FIELDS = {
"email": "String",
"username": "String",
"luck_number": "Int",
}
}
edit 1: adding image
edit 2: adding clarification around my error on register mutation