jammon jammon - 2 months ago 25
Python Question

How can I disable a model field in a django form

I have a model like this:

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


In a view I initialize one field and try to make it non-editable:

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


But the user can still change that field.

What's the real way to accomplish what I'm after?

Answer

Use the HTML readonly attribute:
http://www.w3schools.com/tags/att_input_readonly.asp

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

You can inject arbitrary HTML key value pairs via the widget attrs property:

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

This post has a nice trick for ensuring your form can't accept new values: In a django form, How to make a field readonly (or disabled) so that it cannot be edited?

Override your clean method for your field so that regardless of POST input (somebody can fake a POST, edit the raw HTML, etc.) you get the value you started with.

def clean_status(self):
    return self.instance.status