Администратор Django: как мне отфильтровать виджет ForeignKeyField на основе данных объекта (не request.user)? - PullRequest
2 голосов
/ 15 марта 2012

У меня есть Chart и модели модулей (см. Код ниже).Каждый график принадлежит модулю (через ForeignKey).Диаграмма может иметь другую диаграмму как parent (другую ForeignKey).В админе мне бы хотелось, чтобы выпадающий список parent на конкретном графике включал только графики в том же модуле .

Я ищу решение Python, а не AJAX,Это означает, что при создании новой диаграммы раскрывающийся список должен быть пустым (без экземпляра модели, если модуль не выбран) и что изменение модуля в администраторе не обновит параметры parent, чтобы они соответствовали, пока модель не будет сохранена.Я согласен с этим.

Существует множество похожих вопросов (и ответов), которые, как выясняется, фильтруют параметры в соответствии с user ;ModelAdmin.formfield_for_foreignkey получает запрос в качестве аргумента, так что вы можете использовать request.user, но ему не предоставляется экземпляр модели для игры.(Я использую Django 1.3.)

Мои модели (конечно, очень упрощенные):

class Module(models.Model):
    pass

class Chart(models.Model):
    module = models.ForeignKey(Module)
    parent = models.ForeignKey(Chart, blank=True, null=True)

class ChartAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # I would like to do this, but have no "instance":
        kwargs['queryset'] = Chart.objects.filter(module=instance.module)
        return super(ChartAdmin, self).formfield_for_foreignkey(self, db_field, request, **kwargs)

admin.site.register(Chart, ChartAdmin)

Ответы [ 2 ]

2 голосов
/ 15 марта 2012

Просто переопределите используемый ModelForm:

class ChartAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ChartAdminForm, self).__init__(*args, **kwargs)
        if self.instance.module_id:
            self.fields['parent'].queryset = self.fields['parent'].queryset.filter(module=self.instance.module)

class ChartAdmin(admin.ModelAdmin):
    form = ChartAdminForm
    ...
2 голосов
/ 15 марта 2012

Из того, что я видел в исходном коде, kwargs должен содержать только виджет (не помогает!).

Один из возможных способов взлома - переопределить метод modeladmin get_form (), просто чтобы установитьrequest.current_object.Затем вы можете использовать request.current_object в formfield_callback:

def get_form(self, request, obj=None, **kwargs):
    request.current_object = obj
    return super(ChartAdmin, self).get_form(request, obj, **kwargs)

def formfield_for_foreignkey(self, db_field, request, **kwargs):
    instance = request.current_object

    kwargs['queryset'] = Chart.objects.filter(module=instance.module)
    return super(ChartAdmin, self).formfield_for_foreignkey(self, db_field, request, **kwargs)
...