fields和base_fields - Django

时间:2010-01-26 16:37:41

标签: django django-admin

创建平面页面时,我希望用户从预定义列表中选择模板。为了保持Flatpage模型不变,我更喜欢ChoiceField而不是ModelChoiceField(后者提供了模板的PK,但我需要template_name字段的名称):

class NewFlatpageForm(FlatpageForm):

    template_name = forms.ChoiceField(choices = [])
    def __init__(self, *args, **kwargs):
        self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
        super(NewFlatpageForm, self).__init__(*args, **kwargs)

我重写__init__或者Django在服务器启动时填充选项,然后不更新列表。

我没有任何管理员经验,但在不使用管理员时,我使用fields属性做了类似的事情。但是在这种情况下,我得到一个异常,告诉fields不是表单的属性。 __dict__向我展示了base_fields属性并使用它有效。那么,为什么在这里使用base_fields,为什么fields不存在,最后我做了什么hacky?

3 个答案:

答案 0 :(得分:12)

fields之后调用super后才会存在。所以只需交换行的顺序,以便super首先出现。

答案 1 :(得分:10)

根据我自己的经验教训:修改basefields意味着你的修改“永远”(直到python退出)。在您的情况下,这可能不是问题,因为您始终使用相同的字段名称,并且您正在使用ProjectTemplate中的赋值替换其值...

就我而言,我希望根据构造函数中的参数完全不同的字段。由于我的字段名称通常不同,每次我实例化一个表单时,我都添加了新字段,但没有消除上一次的字段。

通过调用超级早期(如此处所示)然后对self.fields而不是self.basefields进行动态更改,我能够消除不断增长的字段列表的问题。它现在非常有意义,但我不熟悉所有语法细节,并且正在进行攻击,而不是先尝试理解它。

答案 2 :(得分:3)

除了Joe Germuska。如果您确实需要根据请求更改表单,可以使用深度检查来确保通过引用不会更改任何内容:

def get_form(self, request, obj=None, **kwargs):
    form = super(ResourceAdmin, self).get_form(request, obj, **kwargs)
    form = copy.deepcopy(form)

    if obj:
        form.base_fields['email'] = EmailField(initial=obj.user.email)
    if not request.user.is_superuser:
        form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'})

    return form