Users screw up forms in all ways possible so there can be circumstances where you need to disabled or make read only fields when dealing with forms.

Django does provide an easy to use solution to disable a field using widget. But there is no built-in Django form field which will render a value while rejecting bound input data.

self.fields['description'].widget.attrs['readonly'] = True

This can be employed for a fields that ain’t having much significance in application because it does nothing to prevent a POST hack. Small edit to html will let user change data and send via form submission to over ride existing value.

A safer solution is to scrub the input in addition to setting the readonly attribute on the form field

class foo_form(forms.ModelForm):
  def __init__(self, *args, **kwargs):
    super(foo_form, self).__init__(*args, **kwargs)
    instance = getattr(self, 'instance', None)
    if instance and
      self.fields['foo_field'].widget.attrs['readonly'] = True

  def clean_foo_field(self):
    instance = getattr(self, 'instance', None)
    if instance and
      return instance.foo_field
      return self.cleaned_data['foo_field']

The clean_foo_field function will ensure that the readonly value won't be overridden by POST. Other option is to use editable fields in form and get the data in read-only fields from other source outside form.