torchbox / wagtail-grapple

A Wagtail app that makes building GraphQL endpoints a breeze!
https://wagtail-grapple.readthedocs.io/en/latest/
Other
152 stars 57 forks source link

RichTextBlock inside of StructBlock #49

Closed IAmNatch closed 4 years ago

IAmNatch commented 4 years ago

Hi there,

I'm very excited to be using wagtail-grapple after a long while of writing my own nodes in the past.

I think I've found a bug with streamfield rendering, but it may be a bug with wagtail as apposed to grapple.

Essentially, when I render a fields.RichTextField directly on my model, and add a "GraphQLString" to panels, everything works perfectly on my query. As well, when I use a blocks.RichTextBlock() on the root level of my streamfield, it also works perfectly fine as a graphQL query.

The problem arises when I try to use a block.RichTextBlock() inside of a structBlock. Upon doing so I receive null as the value, as well as an error that says expected string or bytes-like object.

My code looks like this:

@register_streamfield_block
class ExampleBlock(blocks.StructBlock):
    heading =  blocks.CharBlock()
    rich_text = blocks.RichTextBlock()

    graphql_fields = [
        GraphQLString('heading'),
        GraphQLString('rich_text'),
    ]
    class Meta:
        label = "Example Block"

class HomePage(Page):
       paragraph = fields.RichTextField(verbose_name="Paragraph")
       body = fields.StreamField(
               [
                   ("heading", blocks.CharBlock(classname="full title")),
                   ("paragraph", blocks.RichTextBlock()),
                   ("image", ImageChooserBlock()),
                   ("example_block", ExampleBlock())
               ],
               blank=True,
              verbose_name="Body",
        )
      .....
     graphql_fields = [
        GraphQLString("title"),
        GraphQLString("paragraph"),
        GraphQLStreamfield("body"),
    ]

As well, my query looks like this:

{
  pages {
    ... on HomePage {
      body {
        blockType
        field
        ... on RichTextBlock {
          value
        }
        ... on ExampleBlock { 
          blocks {
            field
            ... on CharBlock {
              value
            }
            ... on RichTextBlock {
              value
            }
          }
        }
      }
    }
  }
}

With my result looking like this:

{
  "errors": [
    {
      "message": "expected string or bytes-like object"
    }
  ],
  "data": {
    "pages": [
      {},
      {
        "body": [
          {
            "blockType": "RichTextBlock",
            "field": "paragraph",
            "value": "<div class=\"rich-text\"><p>This is amazing!</p></div>"
          },
          {
            "blockType": "ExampleBlock",
            "field": "example_block",
            "blocks": [
              {
                "field": "heading",
                "value": "Simple Heading"
              },
              {
                "field": "rich_text",
                "value": null
              }
            ]
          }
        ]
      }
    ]
  }
}

I've noted that others have encountered similar errors here: https://stackoverflow.com/questions/53790708/django-wagtail-expected-string-or-bytes-like-object-error

I also know my data is in correctly given this value in the DB:

body: [{"type": "example_block", "value": {"heading": "Great Heading", "rich_text": "<h2>Amazing Things</h2><p>Followed by smaller things</p>"}, "id": "cf22bd71-aedf-4ae1-81c2-3c69ff1a5804"}]

I hope this is enough information for us to start getting to the bottom of this. I'm happy to help however I can.

Thanks again for making this!

zerolab commented 4 years ago

May be an issue with the https://github.com/torchbox/wagtail-grapple/blob/master/grapple/types/streamfield.py#L255 definition

Mapping at https://github.com/torchbox/wagtail-grapple/blob/master/grapple/types/streamfield.py#L350

Do you happen to any other error tracebacks?

IAmNatch commented 4 years ago

Hey @zerolab, thanks for the quick reply. This file definitely seems like the culprit.

I do have the following error trace. Please excuse the Docker formatting:

django_1    |   File "/usr/local/lib/python3.7/site-packages/promise/promise.py", line 87, in try_catch
django_1    |     return (handler(*args, **kwargs), None)
django_1    |   File "/usr/local/lib/python3.7/site-packages/graphql/execution/executor.py", line 532, in <lambda>
django_1    |     exe_context, return_type, field_asts, info, path, resolved
django_1    |   File "/usr/local/lib/python3.7/site-packages/graphql/execution/executor.py", line 563, in complete_value
django_1    |     return complete_leaf_value(return_type, path, result)
django_1    |   File "/usr/local/lib/python3.7/site-packages/graphql/execution/executor.py", line 626, in complete_leaf_value
django_1    |     serialized_result = return_type.serialize(result)
django_1    |   File "/usr/local/lib/python3.7/site-packages/graphql/type/scalars.py", line 90, in coerce_string
django_1    |     return text_type(value)
django_1    |   File "/usr/local/lib/python3.7/site-packages/wagtail/core/rich_text/__init__.py", line 49, in __str__
django_1    |     return mark_safe(self.__html__())
django_1    |   File "/usr/local/lib/python3.7/site-packages/wagtail/core/rich_text/__init__.py", line 46, in __html__
django_1    |     return '<div class="rich-text">' + expand_db_html(self.source) + '</div>'
django_1    |   File "/usr/local/lib/python3.7/site-packages/wagtail/core/rich_text/__init__.py", line 32, in expand_db_html
django_1    |     return FRONTEND_REWRITER(html)
django_1    |   File "/usr/local/lib/python3.7/site-packages/wagtail/core/rich_text/rewriters.py", line 99, in __call__
django_1    |     html = rewrite(html)
django_1    |   File "/usr/local/lib/python3.7/site-packages/wagtail/core/rich_text/rewriters.py", line 89, in __call__
django_1    |     return FIND_A_TAG.sub(self.replace_tag, html)
django_1    | TypeError: expected string or bytes-like object
zerolab commented 4 years ago

If you could get the value of html in return FIND_A_TAG.sub(self.replace_tag, html), that would help elucidate things. If not, I will see if I can look into this over the weekend

IAmNatch commented 4 years ago

@zerolab I'd assume it's supposed to be: <h2>Amazing Things</h2><p>Followed by smaller things</p> However if that were the case I imagine things would be working.

I'm not really sure how I'd be able to see that value without overwriting the wagtail/core file. I'll see if I can pull it up in my debugger for more info.

Looking forward to making some headway here!

zerolab commented 4 years ago

@IAmNatch can you check whether https://github.com/GrappleGQL/wagtail-grapple/pull/90 fixes your issue?

IAmNatch commented 4 years ago

@zerolab I can confirm that this has resolved my issue. Thanks to @NathHorrigan and yourself for the help!