hi
i was trying to implement graphql with frappe
i used graphene python . and i have to resolve frappe objects in Query . am trying to find a dynamic way to do it like in graphene-django or graphene-flask so any guides or help ?
if any one interested we can together and push it to frappe ?
using graphql instead of apis call
Are you using JS implementation of graphql?
Where are you actually stuck? Try to generate dictionary of the arguments passed to whitelisted method, you get from graphql and use them as parameters, then return the result.
i have done this so far ⌠am using python graphene
what i have problem with is i have to defiend a class for each doctype i want to resolve like todo for example
class TodoGraphene(graphene.ObjectType):
name = graphene.String()
color = graphene.String()
status = graphene.String()
date = graphene.Date()
def resolve_name(parent, info):
return parent.get("name")
def resolve_color(parent, info):
return parent.get("color")
def resolve_status(parent, info):
return parent.get("status")
def resolve_date(parent, info):
return parent.get("date")
and this is the query :
getdoc = Field(TodoGraphene, doctype=graphene.String(required=True), name=graphene.String(required=True))
def resolve_getdoc(parent, info, **kwargs):
if kwargs.get("doctype") and kwargs.get("name"):
doc = frappe.get_doc(kwargs.get("doctype"), kwargs.get("name"))
fields = [f.fieldname for f in doc.meta.fields]
fields.append('name')
result = {}
for field in fields:
result[field]=doc.get(str(field))
return result
i want TodoGraphene class to be dynmic ⌠i just pass the doctype name and it get all the fields and resolve them , like definded on class and apply to all frappe erpnext docs
can you share your code with me it might help or get me to the right path
This has nothing to do with GraphQL, but you could use doc.as_dict()
or doc.as_json()
to save you some lines:
def resolve_getdoc(parent, info, doctype, name, **kwargs):
doc = frappe.get_doc(doctype, name)
return doc.as_dict()
thanks @rmeyer this save lots of lines
how do you defiend query ?
getdoc = Field(TodoGraphene
, doctype=graphene.String(required=True), name=graphene.String(required=True))
am using a class TodoGraphene and one by one defined type and resolve them, do you use different way ?
Why not use meta-programming?
frappe_to_graphene = {
"Date": graphene.Date
}
def get_graphene_class(doctype, suffix='Graphene'):
from frappe.models import no_value_fields
docfields = frappe.get_all('DocField', fields=['fieldname', 'fieldtype', filters={'parent': doctype}
docfields.extend(frappe.get_all('Custom Field', fields=['fieldname': 'fieldtype'], filters={'dt': doctype}))
attrs={
df.fieldname: frappe_to_graphene.get(df.fieldtype, graphene.String)()
for df in docfields
if df.fieldtype not in no_value_fields
}
def cls_resolve_get_doc(self, parent, info, name, **kwargs)
return resolve_get_doc(parent, info, doctype, **kwargs)
cls_resolve_get_doc.__name__ = "resolve_get_doc"
attrs["resolve_get_doc"] = cls_resolve_get_doc
return type(doctype.replace(' ','').strip() + suffix, (graphene.ObjectType,), attrs)
graphene_doctype = graphene.String(required=True)
graphene_name=graphene.String(required=True)
def get_graphene_get_doc(doctype):
return graphene.Field(get_graphene_class(doctype), doctype=graphene_doctype, name=graphene_name)
def resolve_get_doc(parent, info, doctype, name, **kwargs):
doc = frappe.get_doc(doctype, name)
return doc.as_dict()
ToDoGraphene = get_graphene_class('ToDo')
For sure thereâs various places for improvements, but this define the minimal mechanics for class generation on run-time, using the type
function in in Python
i will try to rewrite it as a class FrappeObjectType
so i can pass meta to it and use it like django does for defending classes
class User(DjangoObjectType):
class Meta:
model = UserModel
fields = (âidâ, âquestion_textâ)
exclude = (âquestion_textâ,)
extra_field = graphene.String()
def resolve_extra_field(self, info):
return 'hello!'
Hi,
It still need a lot of work but we might be able to do this.
i message you we can work together on this
Hey @pipech did you continue working on this after they rejected your PR? the erpnext âRESTâ API is very weird (not very good). For example, itâs common to get a bunch of HTML and even javascript in error messages.
A clean & normal graphql API would be a huge benefit to users and help increase adoption.