For python 3.6.5 using graphene-graphql and mysql-connector
Context: I wrote an API using graphene, a python graphQL implementation, this is actually my first time using the graphQL specification so I’m looking to improve my code implementation for the resolvers using a MySQL database.
As you may know, GraphQL isn’t tied to any specific database or storage engine so it specifies a resolve method, where you “resolve” for a field in your Type. eg. User has a field name, so the resolve method would be how you get that name.
All my types are in a package: mytypes with modules for each type, and they all follow the same styling as the following code example.
Code: Please note how the last two functions are different implementations I’ve tried, more on this on my concerns down below.
import graphene from database.connection import request from mytypes.user import User from mytypes.format import Format _STUDENT_ID = 'SELECT student_id FROM Rubrics WHERE id = %s' _EVALUATOR_ID = 'SELECT evaluator_id FROM Rubrics WHERE id = %s' _PROJECT_NAME = 'SELECT project_name FROM Rubrics WHERE id = %s' class Rubric(graphene.ObjectType): uid = graphene.ID() evaluator = graphene.Field(User) student = graphene.Field(User) rubricFormat = graphene.Field(Format) projectName = graphene.String() evaluationDate = graphene.Date() isPublic = graphene.Boolean() def resolve_evaluator(self, info): evaluator_id = request(_EVALUATOR_ID, self.uid) return User(uid=evaluator_id) def resolve_student(self, info): student_id = request(_STUDENT_ID, self.uid) return User(uid=student_id) def resolve_rubricFormat(self, info): request = 'SELECT format_id FROM Rubrics WHERE id = %s' format_id = make(request, self.uid) return Format(uid=format_id) def resolve_isPublic(self, info): return rubric.is_public(self.uid)
My first concern is about readability, I’m trying to follow the PEP 8 styling for Python code which states that I shouldn’t use or should avoid
More than one space around an assignment (or other) operator to align it with another.
Which I do when defining my fields (uid, evaluator, student, etc), but this way it makes scanning it better in my opinion.
- Resolve Implementation
As for the two methods I mentioned, first for resolve_rubricFormat I like the way make(request, self.uid) was read, where “make” was the same request imported as make but I realized I was just over-complicating.
Then, for resolve_isPublic I was delegating the data fetching to a package resolvers that had modules for every type and had all the logic there, but switching between both the Type and its resolvers/gets at the other package was tiring not to mention the original resolve methods would lose their significance since I was calling another method that was doing what the original resolve was intended for.
- Global Variables
So I switched to global variables where I place the actual SQL query and use it as request(_WHATEVER, id) eg. request(_PROJECT_NAME, self.uid) would return the project name for the specified id, and since its on a module level its understood we are talking about the Rubric id.
But, I’m not sure if this is a good idea, what are your thoughts on this, any way to do it better?