ClassifierSelectWidget should respect `limit_choices_to` on model field

Open
#713 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
django, python
Domain
backend

Research direction

Start at ClassifierSelectWidget.optgroups and inspect how its classifier and term iteration uses self.choices.queryset. Reproduce the provided ParentalManyToManyField example, then verify that only matching terms and non-empty classifier groups are shown and invalid selections no longer pass to form validation.

Written by the indexing model from the issue text.

Description

Type: Bug
Describe the bug

ClassifierSelectWidget always shows all classifiers and terms even if the underlying model field definition restricts choices using limit_choices_to. This allows users to click on invalid options causing the form to fail validation.

Steps to reproduce

Steps to reproduce the behavior:

  1. Set up a classifier with multiple terms. For this example I'm imagining a classifier called "Genre" with the terms "Action", "Adventure", "Horror", "Thriller", "Science-Fiction".
  2. Make a snippet model (new or existing) with the following field:
classifier_terms = ParentalManyToManyField(
    'coderedcms.ClassifierTerm',
    blank=True,
    related_name="genres",
    limit_choices_to=Q(name__startswith="A"), # or any filter eliminates some terms.
)
  1. In the model's panels attribute, include FieldPanel("classifier_terms", widget=ClassifierSelectWidget()).
  2. Run migrations, register snippet, etc.
  3. Go to the snippet edit page for the snippet.
  4. Scroll to the "classifier terms" panel. See that all of the terms are present, not just ones matching the Q object.
  5. Select both a matching term and a non-matching term, and save the form. The form validation should fail and the error message should complain only about the ID of the non-matching term.
Expected behavior

Only the terms and classifiers matching the limit_choices_to filter should be available as choices, as happens when not using the ClassifierSelectWidget(). CheckboxSelectMultiple is very close to what I want, but it is not grouped by classifier.

Additional context

This should theoretically be a simple matter of updating the optgroups class to use self.choices.queryset.

I made a simple working example by changing the initial classifier queryset from Classifier.objects.all().select_related() to



classifiers = Classifier.objects.all().select_related().prefetch_related(
    Prefetch("terms", queryset=self.choices.queryset)
)

to stop Classifiers with no matching terms from appearing as empty groupings, I just changed the inner loop to this:


if terms := classifier.terms.all():
    for term in terms:

If this seems like something y'all would be interested in implementing, I could try my hand at making a merge request. Wanted to confirm that the team would consider it worthwhile.

Dominant language
Python
Stars
765
Forks
154
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from coderedcorp/coderedcms

All issues in coderedcorp/coderedcms

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.