1
votes

I've created custom MarkdownField and MarkdownPanel classes following this tutorial:

from django.db.models import TextField
from django.utils.translation import ugettext_lazy as _

from wagtail.admin.edit_handlers import FieldPanel
from wagtail.utils.widgets import WidgetWithScript

from wagtail.core.blocks import FieldBlock

class MarkdownField(TextField):
    def __init__(self, **kwargs):
        super(MarkdownField, self).__init__(**kwargs)


class MarkdownPanel(FieldPanel):
    def __init__(self, field_name, classname="", widget=None, **kwargs):
        super(MarkdownPanel, self).__init__(
            field_name,
            classname=classname,
            widget=widget,
            **kwargs
        )

        if self.classname:
            if 'markdown' not in self.classname:
                self.classname += "markdown"
        else:
            self.classname = "markdown"


And they work really well as fields:

custom markdown field working well

My goal is to be able to make a custom Block to use it within a StreamField on a page model like this:

class TestPage(Page):
    body = StreamField([
        ('markdown', MarkdownBlock()),
    ])

    content_panels = Page.content_panels + [
        StreamFieldPanel('body')
    ]

    api_fields = [
        APIField('body')
    ]

So I've tried to create a custom Block class as per the Wagtail docs:

... (MarkdownField and MarkdownPanel classes defined above)

class MarkdownBlock(FieldBlock):
    def __init__(self, field_name, classname="", widget=None, **kwargs):
        self.field = MarkdownField()
        super(MarkdownPanel, self).__init__(
            field_name,
            classname=classname,
            widget=widget,
            **kwargs
        )

But I'm met with this error during makemigrations:

File "*******/cms/home/models.py", line 65, in TestPage
    ('markdown', MarkdownBlock()),
TypeError: __init__() missing 1 required positional argument: 'field_name'

I know I'm doing something wrong here, but the documentation doesn't have much advice beyond a basic example and I'm not sure how to properly communicate with my MarkdownField class. I've only seen examples of custom blocks that use combinations of existing blocks, not custom fields. Any help to turn my markdown field into a block would be greatly appreciated!

1

1 Answers

2
votes

Your definition for MarkdownBlock doesn't match the example in the docs - it looks like you've copied and pasted the definition for MarkdownPanel. The correct class definition would be something like:

class MarkdownBlock(FieldBlock):
    def __init__(self, required=True, help_text=None, **kwargs):
        self.field = MarkdownField(required=required, help_text=help_text)
        super().__init__(**kwargs)

Also, note that FieldBlock wraps form fields, not model fields; MarkdownField as defined here is a model field (it inherits from django.db.models.TextField) so using this as the field won't work.