在django-crispy-forms中使用布局对象AppendedText更改单个字段的小部件

4 投票
2 回答
6124 浏览
提问于 2025-04-17 19:24

我正在使用 django-crispy-forms 来渲染一个模型的表单,这个模型是在 django 中创建的。django-crispy-forms 和 Twitter Bootstrap 的结合非常好,并且已经为 AppendedText 这个控件定义了一个布局对象:

AppendedText widget

在我的 django 项目中,我有以下的模型,代码在 models.py 文件里:

class Historia(models.Model):
    persona         = models.ForeignKey('Persona', 
                                  blank=False, 
                                  null=True,
                                  related_name='historias')
    fecha           = models.DateTimeField(unique=True, 
                                auto_now_add=True)
    motivo          = models.TextField()
    peso            = models.DecimalField(blank=True,
                                   max_digits=5, decimal_places=2)
    talla           = models.IntegerField(blank=True)
    tension         = models.CharField(max_length=15)
    pulso           = models.IntegerField()
    diagnostico     = models.TextField()
    tratamiento     = models.TextField()
    pendiente       = models.TextField(blank=True)

然后我在 forms.py 中定义了以下的 modelform

class HistoriaForm(django.forms.ModelForm):
    class Meta:
        model = models.Historia

    def __init__(self, *args, **kwargs):
        super(HistoriaForm, self).__init__(*args, **kwargs)

        self.helper = FormHelper(self)
        self.helper.form_class = 'form-horizontal'
        self.helper.form_tag = True
        self.helper.form_id = 'nueva_historia_form'
        self.helper.form_action = 'nueva_historia'

        self.helper.form_show_errors = True
        self.helper.error_text_inline = False

        self.helper.add_input(Submit('crear', 'Crear'))

我想问的是,如何在不创建新的 widget 子类的情况下,改变 peso 字段的控件,因为 django-crispy-forms 已经定义了一个布局对象。请注意,我不想像下面这样列出所有其他字段:

self.helper.layout = Layout(
            Fieldset(
                'Legend',
                'nombre',
                'apellido',
                AppendedText('peso', 'kg')
            ),
            ButtonHolder(
                Submit('submit', 'Submit', css_class='button white')
            )
        )

因为如果我决定在模型中添加新字段,而这些标准控件已经非常有用了,我就得不断修改这个辅助布局。

编辑:我也看到了一些方法可以通过辅助工具访问布局,比如 self.helper.layout[0] = AppendedText('peso', 'kg'),但我不知道我想要更改的字段的索引。如果我能直接写 self.helper.layout['peso'] = AppendedText('peso', 'kg'),那就太好了。

2 个回答

2

好的,下面是我找到的简单有效的方法,不需要说得太复杂。在__init__方法里,你只需要这样做:

for i, field in enumerate(self.helper.layout):
    if field == 'peso':
        self.helper.layout[i] = AppendedText('peso', 'kg')

如果你要找的字段在layout对象的第一层结构里,这样做是完全没问题的。不过,如果你的字段在一个DIV容器里,你就得更具体一点,先检查一下field.__class__ == DIV,然后再深入查看DIV字段,这可没有看起来那么简单。

不过,要是layout对象的API能支持过滤查询,那就更好了。

7

django-crispy-forms确实有一个接口可以处理这些事情:

http://django-crispy-forms.readthedocs.org/en/latest/dynamic_layouts.html

你可以简单地这样做:

form.helper['peso'].wrap(AppendedText, "kg")

撰写回答