totuk
totuk

Reputation: 25

How to create an abstract GraphQL mutation in Wagtail (Django) with Graphene

I'm trying to make a mutation to create a page in Wagtail using graphene-django. The type of the created page should depend on passed parameters.

All of the pages that are supposed to be created use the same input, which is:

class PageInput(InputObjectType):
    parent_id = Int(required=True)
    page_id = Int(required=True)
    page_name = String(required=True)

, where page_id is the id from the other app and page_name is the record name from the other app - both passed to Mutation as parameters.

Since all pages have the same input, they are supposed to have common mutate() method. What is different for each type is the type-specific prepare_pages() method.

What I want to achieve is to have an abstract CreatePage mutation class, which will define the mutate() method and several classes that inherit this one and implement their own prepare_pages() method.

I implemented the abstract class this way:

class CreatePages(Mutation):
    class Meta:
        abstract = True

    class Arguments:
        pages = List(PageInput)

    page_ids = List(Int)
    creation_times = List(String)

    def prepare_pages(pages):
        raise NotImplementedError("Subclasses must implement this method.")

    @classmethod
    def mutate(cls, root, info, pages):
        page_ids = []
        creation_times = []

        pages_to_create = cls.prepare_pages(pages)

        for page in pages_to_create:
            try:
                page.save_revision().publish()

                page_ids.append(page.page_id)
                creation_times.append(page.latest_revision_created_at
                                      .strftime('%Y-%m-%d %H:%M:%S'))
            except Exception:
                continue

        return cls(page_ids=page_ids, creation_times=creation_times)

The first subclass I want to implement is a CreateProductPage:

class CreateProductPages(CreatePages):

    def prepare_pages(products):
        pages = []
        for product in products:
            try:
                page = ProductPage()
                parent_page = Page.objects.get(id=product.parent_id)

                page.product_id = product.page_id
                page.name = product.page_name if product.page_name else page.product_id
                page.title = page.name
                parent_page.add_child(instance=page)

                pages.append(page)
            except Exception:
                raise
        return pages

While calling a mutation I am continuously getting the following GraphQL error from line parent_page.add_child(instance=page):

{
  "errors": [
    {
      "message": "'NoneType' object has no attribute '_inc_path'",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "createProductPages"
      ]
    }
  ],
  "data": {
    "createProductPages": null
  }
}

How can I solve it? Just to add that while I just had a single Mutation class (not inheriting from the parent class` the creation of a page went smoothly.

Upvotes: 0

Views: 21

Answers (0)

Related Questions