I've tried to find out how "select multiple" is supposed to work but I've failed and I had to give up. It would be really nice to have a minimal example that shows how to implement a custom chooser for m2m relation.
I've tried to use it this way:
class BlogCategoryChooser(AdminChooser):
choose_one_text = _("Choose a blog category")
choose_another_text = _("Choose another blog category")
link_to_chosen_text = _("Edit this blog category")
# choose_modal_url_name = "blog_category_chooser:choose"
icon = "user"
choose_modal_url_name = "blog_category_chooser:chosen_multiple"
@property
def model(self):
return BlogCategory
class EntryPage(Page):
...
categories = ParentalManyToManyField("blogs.BlogCategory", blank=True)
content_panels = [
FieldPanel("categories", widget=BlogCategoryChooser),
]
and this resulted into the following exception
Environment:
Request Method: GET
Request URL: http://localhost:8000/cms/pages/add/blogs/entrypage/69876/
Django Version: 4.1.9
Python Version: 3.9.16
Installed Applications:
['whitenoise.runserver_nostatic',
'django.contrib.auth',
'django.contrib.admin',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.postgres',
'django.contrib.humanize',
'django.forms',
'dal',
'dal_select2',
'django_admin_hstore_widget',
'django_celery_beat',
'django_elasticsearch_dsl',
'django_filters',
'django_extensions',
'django_countries',
'cacheback',
'honeypot',
'crispy_forms',
'psqlextra',
'django_jinja',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_framework',
'wagtail.contrib.forms',
'wagtail.contrib.modeladmin',
'wagtail.contrib.routable_page',
'wagtail.contrib.settings',
'wagtail.contrib.table_block',
'wagtail.contrib.redirects',
'wagtail.embeds',
'wagtail.sites',
'wagtail.users',
'wagtail.snippets',
'wagtail.documents',
'wagtail.images',
'wagtail.search',
'wagtail.admin',
'wagtail',
'modelcluster',
'taggit',
'treebeard',
'captcha',
'meta',
'mathfilters',
'djmoney',
'generic_chooser',
'django_pickling',
'cachalot',
'myproject.core.apps.CoreConfig',
'myproject.ad_integrations.apps.AdIntegrationsConfig',
'myproject.affiliates.apps.AffiliatesConfig',
'myproject.users.apps.UsersConfig',
'myproject.legacy.apps.LegacyConfig',
'myproject.banners.apps.BannersConfig',
'myproject.home.apps.HomeConfig',
'myproject.pages.apps.PagesConfig',
'myproject.menus.apps.MenusConfig',
'myproject.search_terms.apps.SearchTermsConfig',
'myproject.contact.apps.ContactConfig',
'myproject.brands.apps.BrandsConfig',
'myproject.merchants.apps.MerchantsConfig',
'myproject.catalog.apps.CatalogConfig',
'myproject.wishlists.apps.WishlistsConfig',
'myproject.coupons.apps.CouponsConfig',
'myproject.blogs.apps.BlogConfig',
'myproject.sitemaps.apps.SitemapsConfig',
'wagtail.contrib.styleguide']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django_structlog.middlewares.RequestMiddleware',
'django_structlog.middlewares.CeleryMiddleware',
'pyinstrument.middleware.ProfilerMiddleware',
'myproject.core.middleware.SiteMiddleware',
'myproject.catalog.middleware.RedirectMiddleware',
'wagtail.contrib.redirects.middleware.RedirectMiddleware']
Template error:
In template /opt/venv/lib/python3.9/site-packages/wagtail/admin/templates/wagtailadmin/panels/object_list.html, error at line 9
Field 'id' expected a number but got [].
1 : {% load wagtailadmin_tags %}
2 :
3 : <div class="w-form-width">
4 : {% if self.help_text %}
5 : {% help_block status="info" %}{{ self.help_text }}{% endhelp_block %}
6 : {% endif %}
7 : {% for child, identifier in self.visible_children_with_identifiers %}
8 : {% panel id_prefix=self.prefix id=identifier classname=child.classes|join:' ' heading=child.heading heading_size="label" icon=child.icon id_for_label=child.id_for_label is_required=child.is_required %}
9 : {% component child %}
10 : {% endpanel %}
11 : {% endfor %}
12 : </div>
13 :
Traceback (most recent call last):
File "/opt/venv/lib/python3.9/site-packages/django/db/models/fields/__init__.py", line 2018, in get_prep_value
return int(value)
The above exception (int() argument must be a string, a bytes-like object or a number, not 'list') was the direct cause of the following exception:
File "/opt/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 56, in inner
response = get_response(request)
File "/opt/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 220, in _get_response
response = response.render()
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/auth.py", line 203, in overridden_render
return render()
File "/opt/venv/lib/python3.9/site-packages/django/template/response.py", line 114, in render
self.content = self.rendered_content
File "/opt/venv/lib/python3.9/site-packages/django/template/response.py", line 92, in rendered_content
return template.render(context, self._request)
File "/opt/venv/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 175, in render
return self._render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/loader_tags.py", line 63, in render
result = block.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/loader_tags.py", line 63, in render
result = block.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1064, in render
output = self.filter_expression.resolve(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 715, in resolve
obj = self.var.resolve(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 847, in resolve
value = self._resolve_lookup(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 914, in _resolve_lookup
current = current()
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/panels/base.py", line 284, in render_form_content
return mark_safe(self.render_html() + self.render_missing_fields())
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/ui/components.py", line 20, in render_html
return template.render(context_data)
File "/opt/venv/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 175, in render
return self._render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/defaulttags.py", line 238, in render
nodelist.append(node.render_annotated(context))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/defaulttags.py", line 321, in render
return nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1064, in render
output = self.filter_expression.resolve(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 715, in resolve
obj = self.var.resolve(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 847, in resolve
value = self._resolve_lookup(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 914, in _resolve_lookup
current = current()
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/ui/components.py", line 20, in render_html
return template.render(context_data)
File "/opt/venv/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 175, in render
return self._render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/defaulttags.py", line 238, in render
nodelist.append(node.render_annotated(context))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/templatetags/wagtailadmin_tags.py", line 1155, in render
children = self.nodelist.render(context) if self.nodelist else ""
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/opt/venv/lib/python3.9/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/opt/venv/lib/python3.9/site-packages/django/template/library.py", line 237, in render
output = self.func(*resolved_args, **resolved_kwargs)
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/templatetags/wagtailadmin_tags.py", line 1083, in component
return obj.render_html(context)
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/ui/components.py", line 15, in render_html
context_data = self.get_context_data(parent_context)
File "/opt/venv/lib/python3.9/site-packages/wagtail/admin/panels/field_panel.py", line 247, in get_context_data
rendered_field = self.bound_field.as_widget(attrs=widget_attrs)
File "/opt/venv/lib/python3.9/site-packages/django/forms/boundfield.py", line 99, in as_widget
return widget.render(
File "/opt/venv/lib/python3.9/site-packages/wagtail/utils/widgets.py", line 28, in render
value_data = self.get_value_data(value)
File "/opt/venv/lib/python3.9/site-packages/generic_chooser/widgets.py", line 124, in get_value_data
instance = self.get_instance(value)
File "/opt/venv/lib/python3.9/site-packages/generic_chooser/widgets.py", line 79, in get_instance
return self.model.objects.get(pk=value)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py", line 636, in get
clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py", line 1421, in filter
return self._filter_or_exclude(False, args, kwargs)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py", line 1439, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py", line 1446, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "/opt/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1532, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1562, in _add_q
child_clause, needed_inner = self.build_filter(
File "/opt/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1478, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1303, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/lookups.py", line 27, in __init__
self.rhs = self.get_prep_lookup()
File "/opt/venv/lib/python3.9/site-packages/django/db/models/lookups.py", line 341, in get_prep_lookup
return super().get_prep_lookup()
File "/opt/venv/lib/python3.9/site-packages/django/db/models/lookups.py", line 85, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "/opt/venv/lib/python3.9/site-packages/django/db/models/fields/__init__.py", line 2020, in get_prep_value
raise e.__class__(
Exception Type: TypeError at /cms/pages/add/blogs/entrypage/69876/
Exception Value: Field 'id' expected a number but got [].
I've tried to find out how "select multiple" is supposed to work but I've failed and I had to give up. It would be really nice to have a minimal example that shows how to implement a custom chooser for m2m relation.
I've tried to use it this way:
and this resulted into the following exception
Am I missing something?