Example #1
0
    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
            data_url = reverse('{}-api:{}-list'.format(app_label, model_name))
            widget.attrs['data-url'] = data_url

        return bound_field
Example #2
0
    def get_bound_field(self, form, field_name):
        bound_field = BoundField(form, self, field_name)

        # Override initial() to allow passing multiple values
        bound_field.initial = self._get_initial_value(form.initial, field_name)

        # 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:
            filter = self.filter(field_name=self.to_field_name or 'pk', queryset=self.queryset)
            self.queryset = filter.filter(self.queryset, data)
        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
            data_url = reverse('{}-api:{}-list'.format(app_label, model_name))
            widget.attrs['data-url'] = data_url

        return bound_field
Example #3
0
def jet_select2_lookups(field: BoundField):
    form_field: Field = getattr(field, 'field', None)
    if not (form_field and
            (isinstance(form_field, ModelChoiceField)
             or isinstance(form_field, ModelMultipleChoiceField))):
        return field

    qs = form_field.queryset
    model = qs.model

    if not (getattr(model, 'autocomplete_search_fields', None)
            and getattr(form_field, 'autocomplete', True)):
        return field

    choices = []
    app_label = model._meta.app_label
    model_name = model._meta.object_name
    url = getattr(form_field, 'url', reverse('jet:model_lookup'))

    data = getattr(form_field.widget, 'data', {})
    data['blank'] = not form_field.required

    attrs = {
        'class': 'ajax',
        'data-app-label': app_label,
        'data-model': model_name,
        'data-ajax--url': url,
        **format_widget_data(data),
    }

    initial_value = field.value()

    if isinstance(form_field, ModelMultipleChoiceField):
        if initial_value:
            initial_objects = model.objects.filter(pk__in=initial_value)
            choices.extend([(initial_object.pk,
                             get_model_instance_label(initial_object))
                            for initial_object in initial_objects])

        if isinstance(form_field.widget, RelatedFieldWidgetWrapper):
            form_field.widget.widget = SelectMultiple(attrs)
        else:
            form_field.widget = SelectMultiple(attrs)
        form_field.choices = choices
    elif isinstance(form_field, ModelChoiceField):
        if initial_value:
            try:
                initial_object = model.objects.get(pk=initial_value)
                attrs['data-object-id'] = initial_value
                choices.append((initial_object.pk,
                                get_model_instance_label(initial_object)))
            except model.DoesNotExist:
                pass

        if isinstance(form_field.widget, RelatedFieldWidgetWrapper):
            form_field.widget.widget = Select(attrs)
        else:
            form_field.widget = Select(attrs)
        form_field.choices = choices

    return field