Django admin inlines: получить объект из formfield_for_foreignkey

Я пытаюсь отфильтровать параметры, показанные в поле foreignkey, внутри встроенного django admin. Таким образом, я хочу получить доступ к редактируемому родительскому объекту. Я занимаюсь исследованиями, но не нашел решения.

class ProjectGroupMembershipInline(admin.StackedInline):
    model = ProjectGroupMembership
    extra = 1
    formset = ProjectGroupMembershipInlineFormSet
    form = ProjectGroupMembershipInlineForm

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
        if db_field.name == 'group':
            kwargs['queryset'] = Group.objects.filter(some_filtering_here=object_being_edited)
        return super(ProjectGroupMembershipInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

Я проверил, что kwargs пуст при редактировании объекта, поэтому я не могу получить объект оттуда.

Любая помощь, пожалуйста? Благодаря

Ответ 1

Чтобы отфильтровать доступные варианты для поля внешнего ключа в встроенной строке администратора, я переопределяю форму, чтобы обновить атрибут поля формы queryset. Таким образом, вы имеете доступ к self.instance, который является объектом, редактируемым в форме. Так что-то вроде этого:

class ProjectGroupMembershipInlineForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ProjectGroupMembershipInlineForm, self).__init__(*args, **kwargs)
        self.fields['group'].queryset = Group.objects.filter(some_filtering_here=self.instance)

Вам не нужно использовать formfield_for_foreignkey, если вы делаете это, и он должен выполнить то, что вы описали.

Ответ 2

Другой способ, что, ИМХО, чувствует себя чище, чем, но похож на @erichonkanen, ответ примерно такой:

class ProjectGroupMembershipInline(admin.StackedInline):
    # irrelevant bits....

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "group":
            try:
                parent_obj_id = request.resolver_match.args[0]
                kwargs["queryset"] = Group.objects.filter(some_filtering_here=parent_obj_id)
            except IndexError:
                pass
        return super(
            ProjectGroupMembershipInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

Ответ 3

Я смог решить это, используя форму formfield_for_foreignkey и лишив ID объекта из URL. Это не самый сексуальный способ получить идентификатор, но Django еще не предоставляет доступ к ID объекта в объекте admin (он должен).

class ObjectAdmin(admin.ModelAdmin):

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        obj_id = request.META['PATH_INFO'].rstrip('/').split('/')[-1]
        if db_field.name == 'my_field' and obj_id.isdigit():
            obj = self.get_object(request, obj_id)
            if obj:
                kwargs['queryset'] = models.Object.objects.filter(field=obj)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)