Missing information on how to customize the modal
Is it possible to provide examples on how to use the modelchooser in version 4.0.1 (with Wagtail 4.1)? In the past I could easily extend the templates for showing more properties in the modal and also add a search form to it. Basically the last two steps in version 3: https://pypi.org/project/wagtail-modelchooser/3.0.0/
Thank you so much in advance!
No worries, most of that functionality is still there, some of the templates and paths have changes so it was easier to remove that section that it was to update it. If you're considering a heavily customised chooser, I'd recommend looking further into the ChooserViewSet docs, they are very brief but once you dive into the class there's lots of customisation options.
If you wanted do the example from the old readme you could do something like this -
@register_model_chooser
class CityChooser(Chooser):
model = City
modal_template = 'wagtailmodelchooser/city_modal.html'
modal_results_template = \
'wagtailmodelchooser/city_modal_results.html'
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.GET.get('capital'):
qs = qs.filter(capital=request.GET.get('capital') == '0')
return qs
{% extends "wagtailmodelchooser/modal.html" %}
{% block search_fields %}
<ul class="fields">
<li>
<div class="w-field__wrapper">
<label class="w-field__label" for="id_q" id="id_q-label">
Search term
</label>
<div class="w-field w-field--char_field w-field--text_input">
<div class="w-field__input">
<input type="text" name="q" placeholder="Search" id="id_q">
</div>
<div class="w-field__input">
<input type="checkbox" name="capital">
</div>
</div>
</div>
</li>
</ul>
{% endblock %}
{% extends "wagtailmodelchooser/results.html" %}
{% block results_listing %}
<table>
<thead>
<tr>
<th>Name</th>
<th>Is Capital</th>
</tr>
</thead>
<tbody>
{% for result in results %}
<tr>
<td>{{ result }}</td>
<td>{{ result.capital }}</td>
</tr>
</tbody>
</table>
{% endblock %}
Bit messy and I have no idea if this would work properly, the equivalent using the ChooserViewSet would looks something like this
# This is the 'search' view
class CityChooseView(ChooseView):
filter_form_class = CityFilter # A filterset class that inherits from BaseFilterForm and SearchFilterMixin
@property
def columns(self):
columns = super().columns
return columns + [
TitleColumn("capital", label="Is Capital?")
]
class CityChooserViewSet(ChooserViewSet):
model = City
chooser_view_class = CityChooserView
Hey @seb-b,
Thank you for the quick response and providing an example. When I try to use the above I don't see the form though.
{% extends "wagtailmodelchooser/modal.html" %}
{% block search_fields %}
<ul class="fields">
<li>
<div class="w-field__wrapper">
<label class="w-field__label" for="id_q" id="id_q-label">
Search term
</label>
<div class="w-field w-field--char_field w-field--text_input">
<div class="w-field__input">
<input type="text" name="author" placeholder="Author" id="id_author">
</div>
</div>
</div>
</li>
</ul>
{% endblock %}
@register_model_chooser
class BlogAuthorSnippetChooser(Chooser):
model = BlogAuthorSnippet
modal_template = 'snippet/blog_author_modal.html'
# modal_results_template = 'snippet/blog_author_modal_results.html'
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.GET.get('author'):
qs = qs.filter(name__icontains=request.GET.get('author'))
return qs
These are my dependencies: wagtail==4.1.6 wagtail-modelchooser==4.0.1
I have tried overriding the template or even use is_searchable. But I can't seem to add a custom field to it (or a new property in the list).
I managed to do it with a ChooseViewSet!
class BlogAuthorSnippet(index.Indexed, models.Model):
name = models.CharField(max_length=255)
locale = models.ForeignKey('wagtailcore.Locale', on_delete=models.CASCADE, related_name='+')
search_fields = [
index.SearchField('name', partial_match=True)
]
def __str__(self):
return self.name
class Meta:
verbose_name = _('Blog author')
verbose_name_plural = _('Blog authors')
class BlogAuthorChooseView(ChooseView):
@property
def columns(self):
columns = super().columns
return columns + [
Column("locale", label="Locale")
]
class BlogAuthorChooserViewSet(ChooserViewSet):
model = BlogAuthorSnippet
choose_view_class = BlogAuthorChooseView
choose_one_text = "Choose an author"
edit_item_text = "Edit this author"
form_fields = ["name", "locale"]
blog_author_chooser_viewset = BlogAuthorChooserViewSet("blog_author_chooser")
@hooks.register("register_admin_viewset")
def register_viewset():
return blog_author_chooser_viewset
My biggest issue was that I was using filter.IndexField instead of index.SearchField(partial=True). But of course @register_model_chooser is a lot shorter and would prefer to use it like that. The only problem is that I can't seem to add a new column (in my case locale), because the listing template loops through a table instance. Which is why the example given above doesn't work anymore. If you can fix this that would be amazing!