FieldAccessForm (per-field user access for forms derived from models)

 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
from django import forms

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

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)
        if request_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 = None
        exclude = None
        for level in access_levels:
            if not level.rule(request_user, instance): continue
            if level.enable:
                if enable: enable += level.enable
                else: enable = level.enable
            if level.exclude:
                if exclude: exclude += level.exclude
                else: exclude = level.exclude
        # disable all fields except those in enable or exclude
        for fieldname, field in self.fields.items():
            if exclude and fieldname in exclude:
                self.fields.pop(fieldname)
            elif not enable or fieldname not in enable:
                field.widget.attrs['readonly'] = 'readonly'
                field.widget.attrs['disabled'] = 'disabled'
                field.disabled = True
                field.value = getattr(instance, fieldname, '')

More like this

  1. Yet another SQL debugging facility by miracle2k 6 years, 8 months ago
  2. Readonly fields on Form/Modelform by Killarny 5 years, 1 month ago
  3. load m2m fields objects by dirol 3 years, 10 months ago
  4. UTC DateTime field by ludo 6 years, 8 months ago
  5. Functional Filters by waterson 6 years, 6 months ago

Comments

Killarny (on October 24, 2008):

I've updated this to the newest code that I'm using, where I made a few improvements to the syntax of the FieldAccess inner class.

#

(Forgotten your password?)