A Form and ModelForm which provides the ability to specify certain fields as readonly, meaning that they will display their value as text wrapped with a <span> tag. The user is unable to edit them, and they are protected from POST data insertion attacks.
The recommended usage is to place a NewMeta inner class on the form, with a readonly attribute which is a list or tuple of fields, similar to the fields and exclude attributes on the Meta inner class.
class MyForm(ReadonlyForm):
foo = forms.TextField()
bar = forms.TextField()
class NewMeta:
readonly = ('foo',)
Use these forms as you would a standard form in your templates.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | from django import forms
from django.utils.safestring import mark_safe
class SpanWidget(forms.Widget):
'''Renders a value wrapped in a <span> tag.
Requires use of specific form support. (see ReadonlyForm
or ReadonlyModelForm)
'''
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, name=name)
return mark_safe(u'<span%s >%s</span>' % (
forms.util.flatatt(final_attrs), self.original_value))
def value_from_datadict(self, data, files, name):
return self.original_value
class SpanField(forms.Field):
'''A field which renders a value wrapped in a <span> tag.
Requires use of specific form support. (see ReadonlyForm
or ReadonlyModelForm)
'''
def __init__(self, *args, **kwargs):
kwargs['widget'] = kwargs.get('widget', SpanWidget)
super(SpanField, self).__init__(*args, **kwargs)
class Readonly(object):
'''Base class for ReadonlyForm and ReadonlyModelForm which provides
the meat of the features described in the docstings for those classes.
'''
class NewMeta:
readonly = tuple()
def __init__(self, *args, **kwargs):
super(Readonly, self).__init__(*args, **kwargs)
readonly = self.NewMeta.readonly
if not readonly:
return
for name, field in self.fields.items():
if name in readonly:
field.widget = SpanWidget()
elif not isinstance(field, SpanField):
continue
field.widget.original_value = str(getattr(self.instance, name))
class ReadonlyForm(Readonly, forms.Form):
'''A form which provides the ability to specify certain fields as
readonly, meaning that they will display their value as text wrapped
with a <span> tag. The user is unable to edit them, and they are
protected from POST data insertion attacks.
The recommended usage is to place a NewMeta inner class on the
form, with a readonly attribute which is a list or tuple of fields,
similar to the fields and exclude attributes on the Meta inner class.
class MyForm(ReadonlyForm):
foo = forms.TextField()
class NewMeta:
readonly = ('foo',)
'''
pass
class ReadonlyModelForm(Readonly, forms.ModelForm):
'''A ModelForm which provides the ability to specify certain fields as
readonly, meaning that they will display their value as text wrapped
with a <span> tag. The user is unable to edit them, and they are
protected from POST data insertion attacks.
The recommended usage is to place a NewMeta inner class on the
form, with a readonly attribute which is a list or tuple of fields,
similar to the fields and exclude attributes on the Meta inner class.
class Foo(models.Model):
bar = models.CharField(max_length=24)
class MyForm(ReadonlyModelForm):
class Meta:
model = Foo
class NewMeta:
readonly = ('bar',)
'''
pass
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Hi,
it works for me with dropdown lists and text fields.
how can I make it work with checkboxes?
Thanks.
#
This is not working at all for me. It works "fine" up until I try to save a modelform with some fields as read-only. Something in the system tries to verify the readonly fields and I am getting errors.
I'm new to django, and since no one else is complaining about this perhaps it's my code, but I can't figure it out.
#
This doesn't work at all, at least not the base Readonly object, without a ModelForm.
The base Form class doesn't have an 'instance' property.
#
It's even a bit trickier than that; this won't work with initial data, either; you have to actually populate the form with data for this to work.
#
Old snippet I know, but I have a fix for most field types (actually all of the ones I've tested including foreign keys and choice fields).
Replace Line 14:
Replace Line 48:
#
Please login first before commenting.