Как я могу добавить поле выбора, связанное с другой моделью и передать идентификатор текущего объекта? - PullRequest
1 голос
/ 13 февраля 2020

У меня есть форма:

class PersonForm(forms.ModelForm):
    amount = forms.DecimalField(label='Сумма')
    cars = forms.ModelChoiceField(
        queryset=CarProductData.objects.all()
    )

    class Meta:
        labels = {
            'last_name': 'Фамилия',
            'first_name': 'Имя',
            'middle_name': 'Отчество',
            'amount': 'Сумма к списанию',
        }
        fields = ['amount', ]

, и я хочу получить набор запросов внутри admin.ModelAdmin, связанный с текущим объектом, что-то вроде этого:

    def get_form(self, request, obj, **kwargs):
        from django import forms
        from taxi_billing.models import CarProductData
        form = super().get_form(request, obj, **kwargs)
        form.cars = forms.ModelChoiceField(
            queryset=CarProductData.objects.filter(
                product__subscriptionitem__subscription__customer__person__id=obj.id
            )
        )
        return form

Как я могу сделать это сделано?

1 Ответ

1 голос
/ 14 февраля 2020

Я нашел решение. Я должен переопределить метод get_form, который принадлежит ModelAdmin. Просто добавьте поля к new_attrs dict.

       # Add to the dict fields what you need.
        new_attrs['Арнедованные автомобили'] = forms.ModelChoiceField(
            queryset=CarProductData.objects.filter(
                product__subscriptionitem__subscription__customer__person__id=obj.id
            )
        )
    def get_form(self, request, obj=None, change=False, **kwargs):
        """
        Return a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """

        if 'fields' in kwargs:
            fields = kwargs.pop('fields')
        else:
            fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        excluded = self.get_exclude(request, obj)
        exclude = [] if excluded is None else list(excluded)
        readonly_fields = self.get_readonly_fields(request, obj)
        exclude.extend(readonly_fields)
        if change and hasattr(request, 'user') and not self.has_change_permission(request, obj):
            exclude.extend(fields)
        if excluded is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
            exclude.extend(self.form._meta.exclude)
        exclude = exclude or None


        new_attrs = dict.fromkeys(f for f in readonly_fields if f in self.form.declared_fields)

       # Add to the dict fields what you need.
        new_attrs['Арнедованные автомобили'] = forms.ModelChoiceField(
            queryset=CarProductData.objects.filter(
                product__subscriptionitem__subscription__customer__person__id=obj.id
            )
        )

        form = type(self.form.__name__, (self.form,), new_attrs)

        defaults = {
            'form': form,
            'fields': fields,
            'exclude': exclude,
            'formfield_callback': partial(self.formfield_for_dbfield, request=request),
            **kwargs,
        }
        if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
            defaults['fields'] = forms.ALL_FIELDS

        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.'
                % (e, self.__class__.__name__)
            )

...