在Django表单中,我如何使字段只读(或禁用)?

当使用表单创建新条目时,应该启用所有字段——但当记录处于更新模式时,某些字段需要为只读。

例如,当创建一个新的Item模型时,所有字段都必须是可编辑的,但是在更新记录时,是否有一种方法禁用sku字段,使其可见,但不能编辑?

class Item(models.Model):
    sku = models.CharField(max_length=50)
    description = models.CharField(max_length=200)
    added_by = models.ForeignKey(User)


class ItemForm(ModelForm):
    class Meta:
        model = Item
        exclude = ('added_by')

def new_item_view(request):
    if request.method == 'POST':
        form = ItemForm(request.POST)
        # Validate and save
    else:
            form = ItemForm()
    # Render the view

ItemForm类可以重用吗?ItemForm或Item模型类需要做哪些更改?我是否需要编写另一个类“ItemUpdateForm”来更新项目?

def update_item_view(request):
    if request.method == 'POST':
        form = ItemUpdateForm(request.POST)
        # Validate and save
    else:
        form = ItemUpdateForm()

当前回答

基于@paeduardo的回答(这是多余的),你可以在表单类初始化器中禁用一个字段:

class RecordForm(ModelForm):

     def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            var = self.fields['the_field']
            var.disabled = True

其他回答

我认为你最好的选择是在你的模板中包含readonly属性,在<span>或<p>中呈现,而不是在表单中包含它,如果它是readonly的话。

表单用于收集数据,而不是显示数据。也就是说,在只读小部件中显示和清除POST数据的选项是很好的解决方案。

基于@paeduardo的回答(这是多余的),你可以在表单类初始化器中禁用一个字段:

class RecordForm(ModelForm):

     def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            var = self.fields['the_field']
            var.disabled = True

如果你正在使用Django admin,这里有一个最简单的解决方案。

class ReadonlyFieldsMixin(object):
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return super(ReadonlyFieldsMixin, self).get_readonly_fields(request, obj)
        else:
            return tuple()

class MyAdmin(ReadonlyFieldsMixin, ModelAdmin):
    readonly_fields = ('sku',)

对于django 1.9+ 您可以使用Fields disabled参数使字段禁用。 例:在下面forms.py文件的代码片段中,我已经禁用了employee_code字段

class EmployeeForm(forms.ModelForm):
    employee_code = forms.CharField(disabled=True)
    class Meta:
        model = Employee
        fields = ('employee_code', 'designation', 'salary')

参考 https://docs.djangoproject.com/en/dev/ref/forms/fields/#disabled

在小部件上设置readonly只会使浏览器中的输入变为只读。添加一个返回实例的clean_sku。Sku确保字段值不会在表单级别上改变。

def clean_sku(self):
    if self.instance: 
        return self.instance.sku
    else: 
        return self.fields['sku']

这样您就可以使用model的(未修改的保存)并避免获得字段所需的错误。