Source code for data.forms

from crispy_forms.bootstrap import FormActions
from crispy_forms.layout import LayoutObject, Submit
from crispy_forms.utils import TEMPLATE_PACK, render_field
from django import forms
from django.core.exceptions import ValidationError
from django.forms import FileField

__author_orig__ = 'Killarny'
__author__ = 'Jake Merdich'
# Taken from https://djangosnippets.org/snippets/1148/ (it was exactly what I needed)





[docs]class FieldAccessLevel: """Represents an access level for a form.""" def __init__(self, rule, enable=None, exclude=None): self.rule = rule self.enable = enable self.exclude = exclude
[docs]class FieldAccessForm(forms.ModelForm): """This class will grant or deny access to individual fields according to simple rules. Example: class MyForm(FieldAccessForm): class FieldAccess: staff = FieldAccessLevel(lambda u, i: u.is_staff, enable = ('field1', 'field2'), exclude = ('field3',)) """ def __init__(self, request_user, *args, **kwargs): super(FieldAccessForm, self).__init__(*args, **kwargs) self.user = request_user if self.user.is_superuser: # superuser has full access to all fields return instance = kwargs.get('instance', None) # get available access levels access_levels = list() for FieldAccess in (getattr(self, 'FieldAccess', None), getattr(self.Meta.model, 'FieldAccess', None)): if not FieldAccess: continue for attr in dir(FieldAccess): if attr.startswith('_'): continue access_levels += [getattr(FieldAccess, attr)] # for any access level which the user falls under, retrieve the field # access data for those levels enable = [] exclude = [] for level in access_levels: if not level.rule(self.user, instance): continue if level.enable: enable += level.enable if level.exclude: exclude += level.exclude # disable all fields except those in enable or exclude for field_name, field in list(self.fields.items()): if exclude and field_name in exclude: self.fields.pop(field_name) elif not enable or field_name not in enable: field.widget.attrs['readonly'] = 'readonly' field.widget.attrs['disabled'] = 'disabled' field.disabled = True field.required = False field.value = getattr(instance, field_name, '') def _clean_fields(self): for name, field in self.fields.items(): # value_from_datadict() gets the data from the data dictionaries. # Each widget type knows how to retrieve its own data, because some # widgets split data over several HTML fields. # ignore errors and don't store values if a field is disabled if getattr(field, 'disabled', False): continue value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) try: if isinstance(field, FileField): initial = self.initial.get(name, field.initial) value = field.clean(value, initial) else: value = field.clean(value) self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value except ValidationError as e: self.add_error(name, e)
[docs]class DynamicFieldContainer(LayoutObject): def __init__(self, *fields): self.fields = fields
[docs] def render(self, form, form_style, context, template_pack=TEMPLATE_PACK): fields = '' for field in self.fields: try: fields += render_field(field, form, form_style, context, template_pack=template_pack) except Exception: # I really wish dcf had better exception handling continue return fields