{"action":"created","issue":{"url":"https://api.github.com/repos/graphql-python/graphene/issues/583","repository_url":"https://api.github.com/repos/graphql-python/graphene","labels_url":"https://api.github.com/repos/graphql-python/graphene/issues/583/labels{/name}","comments_url":"https://api.github.com/repos/graphql-python/graphene/issues/583/comments","events_url":"https://api.github.com/repos/graphql-python/graphene/issues/583/events","html_url":"https://github.com/graphql-python/graphene/issues/583","id":269333564,"number":583,"title":"Allow separate schema definition & implementation","user":{"login":"lincolnq","id":41908,"avatar_url":"https://avatars2.githubusercontent.com/u/41908?v=4","gravatar_id":"","url":"https://api.github.com/users/lincolnq","html_url":"https://github.com/lincolnq","followers_url":"https://api.github.com/users/lincolnq/followers","following_url":"https://api.github.com/users/lincolnq/following{/other_user}","gists_url":"https://api.github.com/users/lincolnq/gists{/gist_id}","starred_url":"https://api.github.com/users/lincolnq/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lincolnq/subscriptions","organizations_url":"https://api.github.com/users/lincolnq/orgs","repos_url":"https://api.github.com/users/lincolnq/repos","events_url":"https://api.github.com/users/lincolnq/events{/privacy}","received_events_url":"https://api.github.com/users/lincolnq/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2017-10-28T17:10:11Z","updated_at":"2018-02-25T15:24:59Z","closed_at":null,"author_association":"NONE","body":"I would like to separate my Graphene schema definition from its implementation. \r\n\r\n* By \"definition\" I mean the names of my object types, their fields, and custom scalar types.\r\n* By \"implementation\" I mean the `resolve_*` functions and `mutate` functions.\r\n\r\n(Why do I want to do this? Lots of reasons. First, it's super nice to be able to reference all the types and documentation in one place -- putting code in there too makes it far less readable. Second, the implementation requires fancy imports, like accessing my database, that the definition doesn't -- it's nice to be able to import the schema without being forced to import all the database code.)\r\n\r\nCurrently Graphene makes this quite a challenge.\r\n\r\nExample of what I want to do --\r\n\r\n(in graphene_models.py:)\r\n```py\r\nclass User(ObjectType):\r\n    name = String()\r\n\r\nclass Signup(Mutation):\r\n    class Arguments:\r\n        name = String()\r\n    id = ID()\r\n```\r\n\r\n(in graphene_impl.py:)\r\n```py\r\n@resolver_for(User, 'name')\r\ndef resolve_user_name(self, info):\r\n    return 'Cam Newton'\r\n\r\n@mutator_for(Signup)\r\ndef mutate_signup(self, info, name):\r\n    # do something fancy with the db\r\n    return Signup(id=...)\r\n```\r\n\r\nAs things stand today, I can do this, but it's terribly awkward:\r\n* Write the `resolver_for` decorator to monkeypatch the function into, e.g., `User.resolve_name`. This only works if I delay the `Schema` construction till after the implementation module is imported, because it's the TypeMap's job to figure out the resolve functions for the fields and that happens at schema construction time. \r\n* For mutations, I had to look at the resolveinfo's field name and use that to figure out what class's resolver was trying to be executed, and then look for a mutator on that class. (This because the Mutation base class statically binds the mutate method at class creation time, so it's not overridable.)\r\n\r\nI'm mainly curious about whether people agree that having the ability to separate declaration and implementation is desirable, and if so, whether there are any better ways to do it than this, or if there are any plans to improve the situation.\r\n\r\nThanks for your consideration and thanks for writing a very nice piece of software!"},"comment":{"url":"https://api.github.com/repos/graphql-python/graphene/issues/comments/368317962","html_url":"https://github.com/graphql-python/graphene/issues/583#issuecomment-368317962","issue_url":"https://api.github.com/repos/graphql-python/graphene/issues/583","id":368317962,"user":{"login":"jkimbo","id":691952,"avatar_url":"https://avatars1.githubusercontent.com/u/691952?v=4","gravatar_id":"","url":"https://api.github.com/users/jkimbo","html_url":"https://github.com/jkimbo","followers_url":"https://api.github.com/users/jkimbo/followers","following_url":"https://api.github.com/users/jkimbo/following{/other_user}","gists_url":"https://api.github.com/users/jkimbo/gists{/gist_id}","starred_url":"https://api.github.com/users/jkimbo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkimbo/subscriptions","organizations_url":"https://api.github.com/users/jkimbo/orgs","repos_url":"https://api.github.com/users/jkimbo/repos","events_url":"https://api.github.com/users/jkimbo/events{/privacy}","received_events_url":"https://api.github.com/users/jkimbo/received_events","type":"User","site_admin":false},"created_at":"2018-02-25T15:24:59Z","updated_at":"2018-02-25T15:24:59Z","author_association":"CONTRIBUTOR","body":"@lincolnq all fields take a `resolver` parameter so your example can become (without the need for decorators):\r\n\r\n```python\r\n# graphene_models.py\r\n\r\nfrom graphene_impl import resolve_user_name, mutate_signup\r\n\r\nclass User(ObjectType):\r\n\tname = String(resolver=resolve_user_name)\r\n\r\nclass Signup(Mutation):\r\n    class Arguments:\r\n        name = String()\r\n    id = ID()\r\n\r\nclass Mutations(ObjectType):\r\n\tsignup = Signup.Field(resolver=mutate_signup)\r\n```\r\n\r\nOtherwise @HeyHugo 's suggestion would work. Also https://github.com/graphql-python/graphene/issues/448#issuecomment-356777997 has some code that would allow you define your server using the GraphQL Schema Definition Language like [graphql-tools](https://github.com/apollographql/graphql-tools)."}}
{"actor":{"display_login":"jkimbo"}}