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

How to filter the queryset used by the widgets in a form collection? #164

Open
tolland opened this issue Sep 9, 2024 · 2 comments
Open

Comments

@tolland
Copy link

tolland commented Sep 9, 2024

Hi,

I am trying to use the form collections for a set of nested models and filter the queryset for relevant form widgets in the context of the correct "parent" foreign key object. For example using the testapp companies model, if I have a form collection view on some "Department" and department has a field "sales_team" to teams. Then I want to filter the options in the sales_team selection widget in the department form to only those teams in the same department.

To show what I mean, I have added a "sales_team" field to department, which points (nullably) to one of its own teams.

    sales_team = models.ForeignKey(
        "Team",
        on_delete=models.CASCADE,
        related_name='sales_team',
        null=True,
    )

code

I tell the DepartmentForm about the queryset using the __init_method:

    class Meta:
        model = Department
        fields = ['id', 'name', 'sales_team']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # we have current object so get any teams that are related to this department
        if "instance" in kwargs and kwargs["instance"]:
            self.fields["sales_team"].queryset = Team.objects.filter(department_id=kwargs["instance"].id)
        # we don't have an instance so we are creating a new department
        # so no teams to show
        else:
            self.fields["sales_team"].queryset = Team.objects.none()

code

And that works to limit the available sales teams to only those owned by that department:

Screenshot_2024-09-09_13-24-58

That is filtered from the full list of teams:

2024-09-09_13-26

However when this is switched over to using form collections, it stops applying the filters. The problem I am having with form collections is that the modelForms for the collection are initialized during import, so I can't use the "init" method to set the querysets for the widgets.

Like, this Form is created at package import time, so the form can't easily be given any instance data at that time:

2024-09-09_13-32

The collections form version is finding the "teams" for the department:

2024-09-09_13-35

I've been digging about in the code looking for the correct method to override.... can anyone give me a pointer

@tolland
Copy link
Author

tolland commented Sep 9, 2024

I created a fork with my tests here:
https://github.com/jrief/django-formset/compare/releases/1.5...tolland:django-formset:filter-on-parent?expand=1#

there is some fixture data to replicate the compant/team/department fixtures/company.json

@tolland
Copy link
Author

tolland commented Sep 9, 2024

so it seems like I can modify the fieldset used by the widget during the form rendering by overriding get_context:

class MyForm(
    FormMixin,
    ModelForm,
):
...
    def get_context(self):
        self.fields["contact"].queryset = Contact.objects.all()[:10]
        context = super().get_context()
        print(f"context: {context}")
        return context

but I don't see anything in the ModelForm instance that gets passed from the View.... other than the initial object. So maybe pass some extra values in that...?

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

No branches or pull requests

1 participant