About Filtered Autocompletes for Wagtail
If a Wagtail page has a foreign key to a model which you want to have with autocompletion, but the results filtered by some fields, use this technique with a proxy model:
from django.db import models
from django.utils.translation import gettext_lazy as _
from wagtail.admin.panels import FieldPanel
from wagtail.models import Page
from wagtailautocomplete.edit_handlers import AutocompletePanel
class Category(models.Model):
name = models.CharField(_("Name"), max_length=100)
slug = models.SlugField(_("Slug"), unique=True)
class Meta:
verbose_name = _("Category")
verbose_name_plural = _("Categories")
def __str__(self):
return self.name
class Movie(models.Model):
title = models.CharField(_("Title"), max_length=255)
category = models.ForeignKey(
Category,
verbose_name=_("Category"),
on_delete=models.PROTECT,
related_name="movies",
)
class Meta:
verbose_name = _("Movie")
verbose_name_plural = _("Movies")
def __str__(self):
return self.title
def autocomplete_label(self):
return self.title
@classmethod
def autocomplete_custom_queryset_filter(cls, search_term):
return cls.objects.filter(title__icontains=search_term)
class Comedy(Movie):
# Just for the filtered autocomplete widget
class Meta:
proxy = True
verbose_name = _("Comedy")
verbose_name_plural = _("Comedies")
@classmethod
def autocomplete_custom_queryset_filter(cls, search_term):
return (
super()
.autocomplete_custom_queryset_filter(search_term)
.filter(category__slug="comedy")
.distinct()
)
class FilmFestivalEntry(Page):
movie = models.ForeignKey(
# FK still points at the real model, not the proxy
"movies.Movie",
verbose_name=_("Comedy"),
on_delete=models.PROTECT,
limit_choices_to={"category__slug": "comedy"},
related_name="comedy_entries",
)
screening_notes = models.TextField(_("Screening notes"), blank=True)
content_panels = Page.content_panels + [
AutocompletePanel("movie", target_model="movies.Comedy"),
FieldPanel("screening_notes"),
]
Tips and Tricks Programming Django 6.x Django 5.2 Django 4.2 Wagtail 7
Also by me
Django Messaging
For Django-based social platforms.
Django Paddle Subscriptions
For Django-based SaaS projects.
Django GDPR Cookie Consent
For Django websites that use cookies.