问题 为什么我的排除字段仍然出现在这个Django表单中?


我在用着 exclude 在我的表单的Meta类中,从我的表单中排除我想要以编程方式填写的字段,但它仍然在表单中显示。

以下是代码的一些摘录:

# Model
class Info(models.Model):
    completed_by = models.ForeignKey(User, related_name='+')

# Form
class InfoForm(forms.ModelForm):
    class Meta:
        model = Info
        exclude = ('created_by',)  #ETA: added comma to make this a tuple
        widgets = {
            'some_other_field': forms.HiddenInput(),
            'some_other_field2': forms.DateInput(attrs={'readonly': True}),
        }

# View
form = InfoForm(initial={'some_other_field': value}, 
                          prefix='info', instance=info)
return direct_to_template(request, 'myapp/info.html', locals())

# Template
<form class='uniForm' method='POST'>
{% csrf_token %}
<fieldset class='inlineLabels'>{{ form|as_uni_form }}</fieldset>
<input type='submit' name='action' value='Save' />
</form>

这看起来应该很简单,我知道我之前已经成功完成了。我删除/重新创建了我的数据库并清除了我的浏览器缓存,只是为了确保这不是一个因素。我也尝试过制作它 HiddenInput 田野,就像 some_other_field (这是一个 ForeignKey 字段也),但它仍然出现在表格上。

这里有什么东西我不见了吗? uni_form会以某种方式覆盖设置吗?如果没有,有什么建议我可以在调试中寻找什么,看看这是怎么回事?

(使用Django 1.2.7版)


4878
2017-11-15 16:00


起源

如果你只是渲染它仍然会出现 {{ form }} 而不是使用 uni_form ? - second
好主意......是的,它仍然在呈现为{{form}}时出现。 - Ennael
嗯..只是为了确保:你的模型有 completed_by,但你被排除在外 created_by。仅在示例中,对吧? - second
哎呀...是的,就是这样。 :|我猜,太明显了。谢谢您的帮助! - Ennael


答案:


排除需要一个元组,所以你需要

# note the extra comma
exclude = ('created_by',)

django遍历了 exclude,因为字符串是可迭代的(返回每个字符),所以不会引发错误


12
2017-11-15 16:01



你是对的,这应该是一个元组。谢谢。但是,在该修复之后,该字段仍然显示在表单中。 - Ennael
元组+纠正 completed_by/created_by (正如你上面推荐的那样)做到了。再次感谢。 - Ennael
嗯,我这里的运气不好。我排除了这个领域并确保在该领域之后有逗号。该字段仍然会被渲染。 - shailenTJ


对于较旧的Django版本,排除您明确声明的非模型字段存在问题,例如:在父表单类中。在表单的init中添加以下内容即使对于非模型字段也会处理它(请参阅 https://code.djangoproject.com/ticket/8620)。

def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    [self.fields.pop(f) for f in self.fields.keys() if f in self.Meta.exclude]

1
2018-03-04 17:25



谢谢!这也适用于继承的ModelForm,就像我的案例UserWorm wagtail一样。 - Dat TT


我知道这已经过时但是在这里作为参考发布。

我遇到了同样的问题,因为我超载了 clean_fields() 在模型上,但没有正确调用超类。

 class MyModel(models.Model):
    foo = models.BooleanField()    

    # Wrong!  Don't do this!
    def clean_fields(self, exclude=None):
        # Bah!  Forgetting to pass exclude defaults it to None!
        super(MyModel, self).clean_fields()
        if not self.foo:
            raise ValidationError('Ah fooey.')

    # Correct!  Do it this way!
    def clean_fields(self, exclude=None):
        # That's better!  Let's take a coffee break.  I'm tired.
        super(MyModel, self).clean_fields(exclude)
        if not self.foo:
            raise ValidationError('Ah fooey.')

0
2018-02-24 16:52