Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django creating a form field that's read only using widgets

My form field looks something like the following:

class FooForm(ModelForm):
    somefield = models.CharField(
        widget=forms.TextInput(attrs={'readonly':'readonly'})
    )

    class Meta:
        model = Foo

Geting an error like the following with the code above: init() got an unexpected keyword argument 'widget'

I thought this is a legitimate use of a form widget?

like image 779
randombits Avatar asked Dec 01 '09 16:12

randombits


People also ask

How do you make a field readonly in Django?

Setting readonly on a widget only makes the input in the browser read-only. Adding a clean_sku which returns instance. sku ensures the field value will not change on form level. This way you can use model's (unmodified save) and avoid getting the field required error.

What a widget is Django how can you use it HTML input elements?

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 <!

What is form Is_valid () in Django?

The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.


3 Answers

You should use a form field and not a model field:

somefield = models.CharField(
    widget=forms.TextInput(attrs={'readonly': 'readonly'})
)

replaced with

somefield = forms.CharField(
    widget=forms.TextInput(attrs={'readonly': 'readonly'})
)

Should fix it.

like image 188
googletorp Avatar answered Oct 12 '22 23:10

googletorp


Note that the readonly attribute does not keep Django from processing any value sent by the client. If it is important to you that the value doesn't change, no matter how creative your users are with FireBug, you need to use a more involved method, e.g. a ReadOnlyField/ReadOnlyWidget like demonstrated in a blog entry by Alex Gaynor.

like image 26
Benjamin Wohlwend Avatar answered Oct 12 '22 23:10

Benjamin Wohlwend


I was going into the same problem so I created a Mixin that seems to work for my use cases.

class ReadOnlyFieldsMixin(object):
    readonly_fields =()

    def __init__(self, *args, **kwargs):
        super(ReadOnlyFieldsMixin, self).__init__(*args, **kwargs)
        for field in (field for name, field in self.fields.iteritems() if name in self.readonly_fields):
            field.widget.attrs['disabled'] = 'true'
            field.required = False

    def clean(self):
        cleaned_data = super(ReadOnlyFieldsMixin,self).clean()
        for field in self.readonly_fields:
           cleaned_data[field] = getattr(self.instance, field)

        return cleaned_data

Usage, just define which ones must be read only:

class MyFormWithReadOnlyFields(ReadOnlyFieldsMixin, MyForm):
    readonly_fields = ('field1', 'field2', 'fieldx')
like image 27
Michael Avatar answered Oct 13 '22 00:10

Michael