用于可扩展项目的 graphql 代码组织

Posted

技术标签:

【中文标题】用于可扩展项目的 graphql 代码组织【英文标题】:graphql code organization for scalable projects 【发布时间】:2019-03-19 11:01:31 【问题描述】:

假设我们有一个包含大量应用程序的大型项目,这会导致大量查询和突变。对于这样的项目,你们是如何处理 graphql 代码架构的。让我们举个例子。

我有一个名为帐户的应用程序。它将具有与用户和配置文件相关的查询和突变。我使用的文件夹结构是每个应用程序都会有 graphql 文件夹,然后会有 schema.py 和 mutation.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.log('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)

你可以看到仅针对帐户应用程序的突变。有很多突变,考虑到所有应用程序时还会有更多。你们这些人是怎么处理的?

【问题讨论】:

见***.com/questions/45226398/… 【参考方案1】:

我认为仅基于schema.pyqueries.pymutations.py 等文件的项目组织对于大型项目非常不利。

这就像组织您的模型零件,使用 models.pyfields.pyutils.py 等文件...

特别是,在 queries.py 文件中某处定义的 GraphQL ObjectType 可以返回或用作突变的输入。

所以我更喜欢基于对象及其逻辑关系的结构

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代码好吗?

以上是关于用于可扩展项目的 graphql 代码组织的主要内容,如果未能解决你的问题,请参考以下文章

用于从配置文件创建数组的可扩展 C# 代码

Graphql 和 Relay 可扩展性

架构即未来_现代企业可扩展的Web架构流程和组织(原书第2版)pdf

带有图像的可扩展字符串不适用于推送通知

079高性能可扩展MySQL数据库设计及架构优化 电商项目

设置一个可扩展的字符串不适用于简单的 Textview