from django.forms import BoundField from django.urls import reverse from utilities.forms import DynamicModelMultipleChoiceField class CustomDynamicModelMultipleChoiceField(DynamicModelMultipleChoiceField): def get_bound_field(self, form, field_name): bound_field = BoundField(form, self, field_name) # Set initial value based on prescribed child fields (if not already set) if not self.initial and self.initial_params: filter_kwargs = {} for kwarg, child_field in self.initial_params.items(): value = form.initial.get(child_field.lstrip("$")) if value: filter_kwargs[kwarg] = value if filter_kwargs: self.initial = self.queryset.filter(**filter_kwargs).first() # Modify the QuerySet of the field before we return it. Limit choices to any data already bound: Options # will be populated on-demand via the APISelect widget. data = bound_field.value() if data: field_name = getattr(self, "to_field_name") or "pk" filter = self.filter(field_name=field_name) try: self.queryset = filter.filter(self.queryset, data) except (TypeError, ValueError): # Catch any error caused by invalid initial data passed from the user self.queryset = self.queryset.none() else: self.queryset = self.queryset.none() # Set the data URL on the APISelect widget (if not already set) widget = bound_field.field.widget if not widget.attrs.get("data-url"): app_label = self.queryset.model._meta.app_label model_name = self.queryset.model._meta.model_name # # Custom url for work with plugin api # data_url = reverse( "plugins-api:{}-api:{}-list".format(app_label, model_name) ) widget.attrs["data-url"] = data_url return bound_field