wagtail-autocomplete
wagtail-autocomplete copied to clipboard
Autocomplete Manager
As the amount of customization offered on autocompletable objects grows, it seems useful to organize the customizable attributes and methods into a single object. This idea grew out of the discussion in #47.
Currently you can customize autocomplete properties like so:
class MyAutocompletableModel(ClusterableModel):
name = models.CharField(max_length=255)
autocomplete_search_field = 'name'
def autocomplete_label(self):
return self.name
@classmethod
def autocomplete_create(kls: type, value: str):
return kls.objects.create(name=value)
If implemented now, #36 would add yet another classmethod
to the mix. To clean this up and keep it more organized, we'll introduce a new AutocompleteManager
type. The default autocomplete manager would look something like this:
class AutocompleteManager(object):
search_field = 'title'
label_field = 'title'
def search(self, model_class: type, value: str) -> QuerySet:
query_kwargs = {'{}__icontains'.format(self.search_field): value}
return model_class.objects.filter(**query_kwargs)
def label(self, obj: models.Model) -> str:
return getattr(obj, self.label_field)
A subclass of it might look like
class SearchingAutocompleteManager(AutocompleteManager):
def search(self, model_class: type, value: str) -> QuerySet:
return model_class.objects.search(value)
# Notice that no `create` method is specified by default,
# but can be specified on a subclass
def create(self, model_class: type, value: str) -> models.Model:
return model_class.objects.create(title=value)
def label(self, obj: models.Model) -> str:
return obj.__unicode__()
You would register a particular manager with a particular target either declaratively:
class MyAutocompletingPage(Page):
# ...
autocomplete_manager = SearchingAutocompleteManager()
or with a class decorator:
@autocompletable(SearchingAutocompleteManager())
class MyAutocompletingPage(Page):
# ...
Veeeeeery preliminary proof of concept work for this exists on 50-manager
@harrislapiroff this is looking really good. I think a major benefit of breaking things off into a separate component like this is: It could give developers flexibility to list the same model in different ways.
For example:
- Include product codes in an admin-facing list, but only show product names in a public-facing one
- Include draft items in an admin-facing list, but not a public-facing one
- Show the
draft_title
in an admin-facing list, buttitle
in a public-facing one
How difficult do you think it would be to add support for this?