【问题标题】:How can I disable a model field in a django form如何禁用 django 表单中的模型字段
【发布时间】:2011-06-24 03:59:58
【问题描述】:

我有一个这样的模型:

class MyModel(models.Model):
    REGULAR = 1
    PREMIUM = 2
    STATUS_CHOICES = ((REGULAR, "regular"), (PREMIUM, "premium"))
    name = models.CharField(max_length=30)
    status = models.IntegerField(choices = STATUS_CHOICES, default = REGULAR)

class MyForm(forms.ModelForm):
    class Meta:
        model = models.MyModel

在视图中,我初始化一个字段并尝试使其不可编辑:

myform = MyForm(initial = {'status': requested_status})
myform.fields['status'].editable = False

但用户仍然可以更改该字段。

实现我所追求的真正方法是什么?

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    第 1 步:禁用前端小部件

    使用 HTML readonly 属性:
    http://www.w3schools.com/tags/att_input_readonly.asp

    disabled属性:
    http://www.w3.org/TR/html401/interact/forms.html#adef-disabled

    您可以通过小部件 attrs 属性注入任意 HTML 键值对:

    myform.fields['status'].widget.attrs['readonly'] = True # text input
    myform.fields['status'].widget.attrs['disabled'] = True # radio / checkbox
    

    第 2 步:确保在后端有效禁用该字段

    为您的字段覆盖您的 clean 方法,这样无论 POST 输入如何(有人可以伪造 POST、编辑原始 HTML 等),您都可以获得已经存在的字段值。

    def clean_status(self):
        # when field is cleaned, we always return the existing model field.
        return self.instance.status
    

    【讨论】:

    • 哦,不。我试过了,readonly 并没有什么不同。并且 (w3schools.com/tags/att_input_readonly.asp) 说“只读属性可以与 一起使用。”在我的情况下,它是一个选择或单选按钮。那么还有什么想法吗?
    • 嗯,看起来这些按钮的解决方案是 attrs['disabled'] = True w3.org/TR/html401/interact/forms.html#adef-disabled
    • 按我想要的方式工作。谢谢!
    • 卡蒙没问题。如果您觉得满意,请勾选答案旁边的复选标记。
    • 如何选择所有字段?
    【解决方案2】:

    来自 django 1.9:

    from django.forms import Textarea
    
    class MyModelForm(forms.ModelForm):
        class Meta:
            model = MyModel
            fields = '__all__'
            widgets = {'my_field_in_my_model': Textarea(attrs={'cols':80,'rows':1}),}             
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['my_field_in_my_model'].disabled = True
    

    【讨论】:

      【解决方案3】:

      您是否尝试过使用排除功能?

      类似的东西

      class PartialAuthorForm(ModelForm):
      class Meta:
          model = Author
          fields = ('name', 'title')
      
      class PartialAuthorForm(ModelForm):
      class Meta:
          model = Author
          exclude = ('birth_date',)
      

      Reference Here

      【讨论】:

      • 我想改变 per instance 的形式,所以 exclude 不适合我。
      • @jammon:(1)“每个实例”没有意义。您可以有几个不同的子类,以及几个不同的字段组合。 (2) 请更新问题来解释你想要什么。
      【解决方案4】:

      只需自定义状态字段的小部件实例:

      class MyModel(models.Model):
          REGULAR = 1
          PREMIUM = 2
          STATUS_CHOICES = ((REGULAR, "regular"), (PREMIUM, "premium"))
          name = models.CharField(max_length=30)
          status = models.IntegerField(choices = STATUS_CHOICES, default = REGULAR)
      
      class MyForm(forms.ModelForm):
          status =  forms.CharField(widget=forms.TextInput(attrs={'readonly':'True'}))
      
          class Meta:
              model = models.MyModel
      

      见:Django Documentation

      【讨论】:

        【解决方案5】:

        有一个非常简单的方法:

        class GenerateCertificate(models.Model):
        
            field_name = models.CharField(
                max_length=15,
                editable=False)
            def __unicode__(self):
                return unicode(self.field_name)
        

        editable=False 将使该字段无法编辑。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-30
          • 2011-02-04
          • 2020-03-30
          • 1970-01-01
          • 2012-03-02
          • 2013-08-27
          • 2015-06-22
          • 1970-01-01
          相关资源
          最近更新 更多