wagtail / wagtail-generic-chooser

A toolkit for custom chooser popups in Wagtail
BSD 3-Clause "New" or "Revised" License
116 stars 25 forks source link

Wagtail 4.1 AdminChooser fails with TypeError: get_value_data() missing 1 required positional argument: 'value' #66

Closed edward-springload closed 1 year ago

edward-springload commented 1 year ago

I have a subclass of AdminChooser with the following code:

class ProductChooser(AdminChooser):
    choose_one_text = "Choose a Product"
    choose_another_text = "Choose another Product"
    model = Product
    choose_modal_url_name = "product_chooser:choose"

When attempting to load a wagtail page which has a ChooserBlock inside of a StreamBlock, I get the following exception:

Traceback ``` Traceback (most recent call last): File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789381979296), another exception occurred: File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789287318688), another exception occurred: File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789288135168), another exception occurred: File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789286770720), another exception occurred: File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789358757728), another exception occurred: File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789288616576), another exception occurred: File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 318, in build_node existing_node = self.nodes[obj_id] During handling of the above exception (139789358756768), another exception occurred: File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/usr/local/lib/python3.9/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func response = view_func(request, *args, **kwargs) File "/usr/local/lib/python3.9/site-packages/wagtail/admin/urls/__init__.py", line 170, in wrapper return view_func(request, *args, **kwargs) File "/usr/local/lib/python3.9/site-packages/wagtail/admin/auth.py", line 182, in decorated_view response = view_func(request, *args, **kwargs) File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view return self.dispatch(request, *args, **kwargs) File "/usr/local/lib/python3.9/site-packages/wagtail/admin/views/pages/edit.py", line 381, in dispatch return super().dispatch(request) File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch return handler(request, *args, **kwargs) File "/usr/local/lib/python3.9/site-packages/wagtail/admin/views/pages/edit.py", line 424, in get return self.render_to_response(self.get_context_data()) File "/usr/local/lib/python3.9/site-packages/wagtail/admin/views/pages/edit.py", line 873, in get_context_data + self.form.media File "/usr/local/lib/python3.9/site-packages/django/forms/widgets.py", line 165, in _media base = sup_cls.media File "/usr/local/lib/python3.9/site-packages/django/forms/widgets.py", line 165, in _media base = sup_cls.media File "/usr/local/lib/python3.9/site-packages/django/forms/widgets.py", line 165, in _media base = sup_cls.media File "/usr/local/lib/python3.9/site-packages/django/forms/widgets.py", line 165, in _media base = sup_cls.media File "/usr/local/lib/python3.9/site-packages/django/forms/widgets.py", line 165, in _media base = sup_cls.media File "/usr/local/lib/python3.9/site-packages/modelcluster/forms.py", line 355, in media media = super().media File "/usr/local/lib/python3.9/site-packages/django/forms/widgets.py", line 165, in _media base = sup_cls.media File "/usr/local/lib/python3.9/site-packages/django/forms/forms.py", line 456, in media media = media + field.widget.media File "/usr/local/lib/python3.9/site-packages/django/utils/functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/usr/local/lib/python3.9/site-packages/wagtail/blocks/base.py", line 561, in media return self.js_context.media + forms.Media( File "/usr/local/lib/python3.9/site-packages/wagtail/blocks/base.py", line 517, in js_context self._build_block_json() File "/usr/local/lib/python3.9/site-packages/wagtail/blocks/base.py", line 512, in _build_block_json self._block_json = json.dumps(self._js_context.pack(self.block_def)) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 220, in pack return ValueContext(self).build_node(obj).emit() File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 339, in _build_new_node return adapter.build_node(obj, self) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 169, in build_node constructor, [context.build_node(arg) for arg in args] File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 169, in constructor, [context.build_node(arg) for arg in args] File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in _build_new_node return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in _build_new_node return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in _build_new_node return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 339, in _build_new_node return adapter.build_node(obj, self) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 169, in build_node constructor, [context.build_node(arg) for arg in args] File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 169, in constructor, [context.build_node(arg) for arg in args] File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in _build_new_node return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 354, in return ListNode([self.build_node(item) for item in items]) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 321, in build_node node = self._build_new_node(val) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 339, in _build_new_node return adapter.build_node(obj, self) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 167, in build_node constructor, args = self.pack(obj, context) File "/usr/local/lib/python3.9/site-packages/telepath/__init__.py", line 164, in pack return (self.js_constructor, self.js_args(obj)) File "/usr/local/lib/python3.9/site-packages/wagtail/blocks/stream_block.py", line 738, in js_args { File "/usr/local/lib/python3.9/site-packages/wagtail/blocks/stream_block.py", line 739, in name: child_block.get_form_state(child_block.get_default()) File "/usr/local/lib/python3.9/site-packages/wagtail/blocks/field_block.py", line 816, in get_form_state return self.widget.get_value_data(value) Exception Type: TypeError at /admin/pages/3/edit/ Exception Value: get_value_data() missing 1 required positional argument: 'value' ```
gasman commented 1 year ago

Are you using the chooser block definition from https://github.com/wagtail/wagtail-generic-chooser#streamfield-blocks? If not, please can you share the relevant code from your StreamField definition?

edward-springload commented 1 year ago

Here is the ChooserBlock:

class ProductChooserBlock(ChooserBlock):
    class Meta:
        icon = "fa-shopping-cart"

    target_model = Product

    @cached_property
    def widget(self):
        from shop.widgets import ProductChooser

        return ProductChooser

    def render_basic(self, value, context=None):
        if value:
            return format_html(
                '<a href="{0}">{1}</a>', value.get_absolute_url(), value.title
            )
        else:
            return ""

Relevant StreamBlock (this is inside a StructBlock class definition:

    main_publication = blocks.StreamBlock(
        [
            (
                "free_publication",
                blocks.PageChooserBlock(
                    target_model="core.PublicationPage", required=True
                ),
            ),
            ("product", ProductChooserBlock()),
        ],
        max_num=1,
        required=True,
        help_text="Only one publication may be be added",
        label="Publication",
    )
gasman commented 1 year ago

Adding the get_form_state method from https://github.com/wagtail/wagtail-generic-chooser#streamfield-blocks to ProductChooserBlock should hopefully fix this.

edward-springload commented 1 year ago

I had already tried it. Thanks for you help. What is interesting that it seems this worked before:

    @cached_property
    def widget(self):
        from shop.widgets import ProductChooser

        return ProductChooser

But we now have to instantiate the chooser class and do return ProductChooser(). Which makes sense given the original error.