wagtail-grapple
wagtail-grapple copied to clipboard
Need to work via a through model
I have an explicit through model, with which I define a Many-to-Many relationship to allow the related items to be orderable in wagtail.
I've succeeded in getting this to work with grapple as shown below (for posterity should anyone need the same).
However, the query and response are messy, you have to go all the way through the through model. I'm wondering if there's a more elegant way of achieving this (see below).
The example:
@register_snippet
class Section(index.Indexed, Model):
name = CharField(max_length=80)
# ... and other fields, and panels etc etc ...
graphql_fields = [
GraphQLString("name"),
]
class PageSectionsOrderable(Orderable):
""" This through-model allows us to select and reorder one or more Sections from the *Section snippets
"""
page = ParentalKey('cms_site.SitePage', on_delete=CASCADE, related_name='sections')
section = ForeignKey('cms_site.Section', on_delete=CASCADE, related_name='pages')
panels = [
SnippetChooserPanel('section'),
]
graphql_fields = [
GraphQLInt('section_id'),
GraphQLForeignKey('section', 'cms_site.Section')
]
class SitePage(Page):
""" SitePage is used to manage SEO data and general website content including hero banners
"""
# ... fields, content panels, etc ...
graphql_fields = [
GraphQLString("subtitle_text"),
GraphQLCollection(
GraphQLForeignKey,
"sections",
"cms_site.PageSectionsOrderable"
),
]
We'd use the following query to get the Sections with the pages:
{
pages {
...on SitePage {
subtitleText
sections {
section {
id
name
}
}
}
}
}
Which gives the response:
{
"data": {
"pages": [
{},
{
"title": "Its a page with two sections",
"sections": [
{
"section": {
"id": "1",
"name": "Section The First"
}
},
{
"section": {
"id": "2",
"name": "Section The Second"
}
}
]
}
]
}
}
Is there a sensible way to collapse the sections to remove the extra { "section": {} }
in the graph structure? My first instinct is to start dabbling with creating a GraphQLThrough
field in grapple
but being a total newbie with GraphQL, I'm wondering if this will massively screw up some fundamental paradigms?
Would be pleased to hear any thoughts anyone has on that approach?
Interesting question... I generally create a property on the model that looks something like this:
class SitePage(Page):
...
@property
def direct_accessor_for_sections(self): # normally, I'd just call this "sections", and give the association model a name indicative of it being an association model.
return Section.objects.filter(pages__page=self)
If there's a way to add a graphql field containing this property instead of a direct database field you should be able to achieve your goal, it would seem? Maybe try something like:
GraphQLCollection(
GraphQLForeignKey,
'direct_accessor_for_sections', # Terrible name, but for now this refers to our property containing the queryset of Sections.
'cms_site.Section',
),
@thclark were you ever able to figure this our?