Read only form & model field

 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
from django.db import models

# Decorator for django models that contain readonly fields.
def has_readonly_fields(original_class):
    def store_read_only_fields(sender, instance, **kwargs):
        if not instance.id:
            return
        for field_name in sender.read_only_fields:
            val = getattr(instance, field_name)
            setattr(instance, field_name + "_oldval", val)

    def check_read_only_fields(sender, instance, **kwargs):
        if not instance.id:
            return
        for field_name in sender.read_only_fields:
            old_value = getattr(instance, field_name + "_oldval")
            new_value = getattr(instance, field_name)
            if old_value != new_value:
                raise ValueError("Field %s is read only." % field_name)

    models.signals.post_init.connect(store_read_only_fields, original_class, weak=False) # for load
    models.signals.post_save.connect(store_read_only_fields, original_class, weak=False) # for save
    models.signals.pre_save.connect(check_read_only_fields, original_class, weak=False)
    return original_class

# decorator for django modelforms that contain readonly fields
def modelform_with_readonly_fields(origin_class):
    origin_init = origin_class.__init__

    def lambder(field, old_method):
        return lambda this : clean_field(this, field, old_method)

    def clean_field(self, field_name, old_method):
        instance = getattr(self, 'instance', None)
        if instance and instance.id:
            return getattr(instance, field_name)
        else:
            if old_method:
                return old_method(self)
            else:
                return self.cleaned_data.get(field_name, None)

    def __init__(self, *args, **kws):
        origin_init(self, *args, **kws)
        instance = getattr(self, 'instance', None)
        if instance and instance.id:
            for field in origin_class.Meta.model.read_only_fields:
                self.fields[field].required = False
                self.fields[field].widget.attrs['disabled'] = 'disabled'

    origin_class.__init__ = __init__

    for field in origin_class.Meta.model.read_only_fields:
        field_name = "clean_" + field
        old_method = getattr(origin_class, field_name, None)
        setattr(origin_class, field_name, lambder(field, old_method))
    return origin_class

More like this

  1. Readonly admin fields by peritus 4 years, 9 months ago
  2. Readonly fields on Form/Modelform by Killarny 4 years, 2 months ago
  3. Add a CSS class to every field indicating what kind of field it is by ramen 2 years, 10 months ago
  4. Optimistic locking in Admin by Taifu 1 year, 9 months ago
  5. Template tag to create a list from one or more variables and/or literals by davidchambers 2 years, 8 months ago

Comments

(Forgotten your password?)