Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autocomplete Manager #50

Open
harrislapiroff opened this issue May 17, 2019 · 2 comments
Open

Autocomplete Manager #50

harrislapiroff opened this issue May 17, 2019 · 2 comments

Comments

@harrislapiroff
Copy link
Collaborator

harrislapiroff commented May 17, 2019

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):
    # ...
@harrislapiroff
Copy link
Collaborator Author

Veeeeeery preliminary proof of concept work for this exists on 50-manager

@ababic
Copy link

ababic commented Nov 16, 2019

@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, but title in a public-facing one

How difficult do you think it would be to add support for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants