2012-03-15 3 views
2

У меня есть Chart и модели модулей (см. Код ниже). Каждый график принадлежит модулю (через ForeignKey). Диаграмма может иметь другую диаграмму как ее parent (другая ForeignKey). Я бы хотел, чтобы в админе выпадающий список для parent на конкретном графике только включает в себя схемы в этом модуле.Django admin: как я могу фильтровать виджет ForeignKeyField на основе данных объекта (а не request.user)?

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

Есть много похожих вопросов (и ответов), которые, оказывается, фильтруют параметры в соответствии с пользователем ; 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

Просто переопределение 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 
    ... 
+0

Великое, спасибо! Я добавил редактирование (в очереди), чтобы сделать его безопасным, например, создание (когда self.instance.module вызывает DoNotExist). – Tikitu

2

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

Одним из возможных взломов было бы переопределить метод get_form() modeladmin, чтобы установить 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) 
+0

Благодаря jpic, просто использовали свой код и отлично работает – Nick

 Смежные вопросы

  • Нет связанных вопросов^_^