模板中的只读表单,django

Posted

技术标签:

【中文标题】模板中的只读表单,django【英文标题】:Read-only form in template, django 【发布时间】:2015-08-19 12:12:14 【问题描述】:

如何在模板上而不是在模型或视图中将输入设为只读?

例如在

% for form in formset %
             form.id 
            <tr>
                <th> form.project_name </th>

如果可能的话,我需要通过 html form.project_name 设为只读(仍为表单)(它在 model.py 中有默认值)

编辑。我需要它是只读的浏览器,而不是只读的表单。

【问题讨论】:

In a django form, How to make a field readonly (or disabled) so that it cannot be edited?的可能重复 实际上并不完全,我需要通过 html 禁用它们,就像我可以在 html 中使用 &lt;input readonly&gt; 一样。 如果您在表单上设置只读,它会为您执行此操作,如果您阅读了最佳答案,除了其他保护之外。 【参考方案1】:

如果您想让所有字段在模板级别只读,请使用 HTML &lt;fieldset&gt; disabled 属性:

    <form action="% url "app.views.fonction" %" method="post">% csrf_token %
        <h2>% trans "Any title" %</h2>
        <fieldset disabled="disabled">
             form.as_ul 
        </fieldset>
    <input type="submit" class="any" value="any" />
    </form>

【讨论】:

【参考方案2】:

如果您想在 HTML 中创建 input 字段 readonly,您必须自己编写所有必需的 HTML。

HTML

<input type="text" value=" object.field_1 " readonly />
<input type="text" value=" object.field_2 " readonly />

<!-- And so on -->

【讨论】:

【参考方案3】:

有一个很好的答案here:

您可以通过小部件的 attributes 属性将必要的 html 添加到表单字段:

myform.fields['thefield'].widget.attrs['readonly'] = True

这样你仍然可以在模板中书写

myform.thefield.label_tag
myform.thefield

Django 会将readonly="True" 放入&lt;input ...&gt;

【讨论】:

【参考方案4】:

最简洁的方法是创建一个具有只读字段meta 选项的新表单基类,并为您完成其余工作。

您不应该在模板中包含任何逻辑,而是在视图中验证数据,并将 let django 呈现只读输入作为span widget

我在生产中使用它并取得了巨大成功。

class SpanWidget(forms.Widget):
    '''Renders a value wrapped in a <span> tag.

    Requires use of specific form support. (see ReadonlyForm
    or ReadonlyModelForm)
    '''

    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, name=name)
        return mark_safe(u'<span%s >%s</span>' % (
            forms.util.flatatt(final_attrs), self.display_value))

    def value_from_datadict(self, data, files, name):
        return self.original_value


class SpanField(forms.Field):
    '''A field which renders a value wrapped in a <span> tag.

    Requires use of specific form support. (see ReadonlyForm
    or ReadonlyModelForm)
    '''

    def __init__(self, *args, **kwargs):
        kwargs['widget'] = kwargs.get('widget', SpanWidget)
        super(SpanField, self).__init__(*args, **kwargs)
class Readonly(object):
    '''Base class for ReadonlyForm and ReadonlyModelForm which provides
    the meat of the features described in the docstings for those classes.
    '''

    class NewMeta:
        readonly = tuple()

    def __init__(self, *args, **kwargs):
        super(Readonly, self).__init__(*args, **kwargs)
        readonly = self.NewMeta.readonly
        if not readonly:
            return
        for name, field in self.fields.items():
            if name in readonly:
                field.widget = SpanWidget()
            elif not isinstance(field, SpanField):
                continue
            model_field = self.instance._meta.get_field_by_name(name)[0]
            field.widget.original_value = model_field.value_from_object(self.instance)
            field.widget.display_value = unicode(getattr(self.instance, name))


class ReadonlyForm(Readonly, forms.Form):
    '''A form which provides the ability to specify certain fields as
    readonly, meaning that they will display their value as text wrapped
    with a <span> tag. The user is unable to edit them, and they are
    protected from POST data insertion attacks.

    The recommended usage is to place a NewMeta inner class on the
    form, with a readonly attribute which is a list or tuple of fields,
    similar to the fields and exclude attributes on the Meta inner class.

        class MyForm(ReadonlyForm):
            foo = forms.TextField()
            class NewMeta:
                readonly = ('foo',)
    '''
    pass


class ReadonlyModelForm(Readonly, forms.ModelForm):
    '''A ModelForm which provides the ability to specify certain fields as
    readonly, meaning that they will display their value as text wrapped
    with a <span> tag. The user is unable to edit them, and they are
    protected from POST data insertion attacks.

    The recommended usage is to place a NewMeta inner class on the
    form, with a readonly attribute which is a list or tuple of fields,
    similar to the fields and exclude attributes on the Meta inner class.

        class Foo(models.Model):
            bar = models.CharField(max_length=24)

        class MyForm(ReadonlyModelForm):
            class Meta:
                model = Foo
            class NewMeta:
                readonly = ('bar',)
    '''
    pass

这是我在production中使用的代码:

class MembershipForm(ReadonlyModelForm):
    class Meta:
        model = Membership
        fields = ('user','board', 'privileged', 'alumni')

    class NewMeta:
        readonly = ('user')
    def email(self):
        return self.instance.user.email

【讨论】:

以上是关于模板中的只读表单,django的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Django 中的只读表单字段是个坏主意?

Django:未提交表单中的只读字段

Django 表单中的只读字段

如何在 django 模型表单中添加自定义字段?

Django:模板中的 Crispy 表单验证错误

使用 CBV 在 Django 中的一个视图/模板中的两个模型表单