Подумайте, что у нас есть большой проект с множеством приложений, который приводит к множеству запросов и мутаций. Для таких проектов, как вы, люди, обращаетесь с архитектурой кода graphql. Возьмем пример.
У меня есть приложение под названием Accounts. В нем будут запросы и изменения, связанные с пользователем и профилем. Структура папок, которую я использую, заключается в том, что каждое приложение будет иметь папку graphql, которая затем будет иметь schema.py и mutations.py. Код пока устроен примерно так
schema.py
class User(DjangoObjectType):
class Meta:
model = CustomUser
filter_fields = {
'email': ['exact', ],
}
exclude_fields = ('password', 'is_superuser', )
interfaces = (relay.Node, )
class ProfileNode(DjangoObjectType):
class Meta:
model = Profile
interfaces = (relay.Node, )
class UserQuery(object):
user = relay.Node.Field(User)
users = DjangoFilterConnectionField(User) # resolve_users is not needed now
class ProfileQuery(object):
profile = relay.Node.Field(ProfileNode)
profiles = DjangoFilterConnectionField(ProfileNode)
class UserProfile(ObjectType):
profile = Field(ProfileNode)
def resolve_profile(self, info, **kwargs):
if id is not None and info.context.user.is_authenticated:
profile = Profile.objects.get(user=info.context.user)
return profile
return None
class Viewer(ObjectType):
user = Field(User)
def resolve_user(self, info, **kwargs):
if info.context.user.is_authenticated:
return info.context.user
return None
mutations.py
class Register(graphene.Mutation):
"""
Mutation to register a user
"""
class Arguments:
first_name = graphene.String(required=True)
last_name = graphene.String(required=True)
email = graphene.String(required=True)
password = graphene.String(required=True)
password_repeat = graphene.String(required=True)
success = graphene.Boolean()
errors = graphene.List(graphene.String)
def mutate(self, info, first_name, last_name, email, password, password_repeat):
# console.info('info', info, first_name, last_name, email, password)
if password == password_repeat:
try:
user = CustomUser.objects.create(
first_name=first_name,
last_name=last_name,
email=email,
is_active=False
)
print ('user', user)
user.set_password(password)
user.save()
if djoser_settings.get('SEND_ACTIVATION_EMAIL'):
send_activation_email(user, info.context)
return Register(success=bool(user.id))
# TODO: specify exception
except Exception:
errors = ["email", "Email already registered."]
return Register(success=False, errors=errors)
errors = ["password", "Passwords don't match."]
return Register(success=False, errors=errors)
корневая схема
// just to show the number of mutations just for account apps.
from accounts.graphql.mutations import (
Activate,
DeleteAccount,
Login,
RefreshToken,
Register,
ResetPassword,
ResetPasswordConfirm,
)
from accounts.graphql.schema import Viewer, UserProfile
class Mutation(company_mutation.Mutation, graphene.ObjectType):
activate = Activate.Field()
debug = graphene.Field(DjangoDebug, name='__debug')
class Query(company_schema.Query, graphene.ObjectType):
viewer = graphene.Field(Viewer)
user_profile = graphene.Field(UserProfile)
debug = graphene.Field(DjangoDebug, name='__debug')
@staticmethod
def resolve_viewer(self, info, **kwargs):
if info.context.user.is_authenticated:
return info.context.user
return None
@staticmethod
def resolve_user_profile(self, info, **kwargs):
if info.context.user.is_authenticated and id:
return info.context.user
return None
schema = graphene.Schema(query=Query, mutation=Mutation)
вы можете видеть мутации только для приложений учетных записей. Мутаций много, и их будет больше, если рассматривать все приложения. Как вы справляетесь с такими?






Я считаю, что организация проекта, основанная только на файлах типа schema.py, queries.py, mutations.py, очень плохо для большого проекта.
Это похоже на организацию частей вашей модели с помощью таких файлов, как models.py, fields.py, utils.py ...
В частности, GraphQL ObjectType, определенный где-то в вашем файле queries.py, может быть возвращен или использован в качестве входных данных при мутации.
Поэтому я предпочитаю структуру, больше основанную на объектах и их логических отношениях.
schema/
__init__.py : contains your root schema actual code
viewer.py : contains the ObjectType Viewer
user/
user.py : contains the ObjectType User and UserQuery
profile.py : contains the ObjectType Profil
account : contains the account management mutations
login.py : contains the login / logout mutations
...
Примечание: вы можете внедрять мутации так же, как и запросы, чтобы иметь возможность получать такие запросы мутаций, как:
mutation {
account {
delete(id: 12) {
status
}
}
}
Не могли бы вы добавить код Python, который показывает, как организовать подобные мутации?
См. stackoverflow.com/questions/45226398/…