Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a Django form, how do I make a field readonly (or disabled) so that it cannot be edited?

In a Django form, how do I make a field read-only (or disabled)?

When the form is being used to create a new entry, all fields should be enabled - but when the record is in update mode some fields need to be read-only.

For example, when creating a new Item model, all fields must be editable, but while updating the record, is there a way to disable the sku field so that it is visible, but cannot be edited?

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 

Can class ItemForm be reused? What changes would be required in the ItemForm or Item model class? Would I need to write another class, "ItemUpdateForm", for updating the item?

def update_item_view(request):     if request.method == 'POST':         form = ItemUpdateForm(request.POST)         # Validate and save     else:         form = ItemUpdateForm() 
like image 400
X10 Avatar asked Nov 27 '08 18:11

X10


People also ask

What is widget in Django?

A widget is Django's representation of an HTML input element. The widget handles the rendering of the HTML, and the extraction of data from a GET/POST dictionary that corresponds to the widget. The HTML generated by the built-in widgets uses HTML5 syntax, targeting <!

How do I add a class or id attribute to a Django form field?

In order to add a class or id attribute to a form in Django, we have to place a widget=form. TextInput (or widget= form. EmailInput, if email input) within the form field (because it's a text field). Inside of this widget, we then have to put, attrs={'class':'some_class'}.

How do you make a field not editable in Django?

The disabled boolean argument, when set to True , disables a form field using the disabled HTML attribute so that it won't be editable by users. Even if a user tampers with the field's value submitted to the server, it will be ignored in favor of the value from the form's initial data.


1 Answers

As pointed out in this answer, Django 1.9 added the Field.disabled attribute:

The disabled boolean argument, when set to True, disables a form field using the disabled HTML attribute so that it won’t be editable by users. Even if a user tampers with the field’s value submitted to the server, it will be ignored in favor of the value from the form’s initial data.

With Django 1.8 and earlier, to disable entry on the widget and prevent malicious POST hacks you must scrub the input in addition to setting the readonly attribute on the form field:

class ItemForm(ModelForm):     def __init__(self, *args, **kwargs):         super(ItemForm, self).__init__(*args, **kwargs)         instance = getattr(self, 'instance', None)         if instance and instance.pk:             self.fields['sku'].widget.attrs['readonly'] = True      def clean_sku(self):         instance = getattr(self, 'instance', None)         if instance and instance.pk:             return instance.sku         else:             return self.cleaned_data['sku'] 

Or, replace if instance and instance.pk with another condition indicating you're editing. You could also set the attribute disabled on the input field, instead of readonly.

The clean_sku function will ensure that the readonly value won't be overridden by a POST.

Otherwise, there is no built-in Django form field which will render a value while rejecting bound input data. If this is what you desire, you should instead create a separate ModelForm that excludes the uneditable field(s), and just print them inside your template.

like image 121
Daniel Naab Avatar answered Sep 22 '22 17:09

Daniel Naab