File: forms.py

package info (click to toggle)
django-dynamic-preferences 1.17.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 476 kB
  • sloc: python: 3,040; makefile: 3
file content (151 lines) | stat: -rw-r--r-- 5,152 bytes parent folder | download
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
from django import forms
from django.core.exceptions import ValidationError
from collections import OrderedDict

from .registries import global_preferences_registry
from .models import GlobalPreferenceModel
from .exceptions import NotFoundInRegistry


class AbstractSinglePreferenceForm(forms.ModelForm):
    class Meta:
        fields = ("section", "name", "raw_value")

    def __init__(self, *args, **kwargs):

        self.instance = kwargs.get("instance")
        initial = {}
        if self.instance:
            initial["raw_value"] = self.instance.value
            kwargs["initial"] = initial
        super(AbstractSinglePreferenceForm, self).__init__(*args, **kwargs)

        if self.instance.name:
            self.fields["raw_value"] = self.instance.preference.setup_field()

    def clean(self):
        cleaned_data = super(AbstractSinglePreferenceForm, self).clean()
        try:
            self.instance.name, self.instance.section = (
                cleaned_data["name"],
                cleaned_data["section"],
            )
        except KeyError:  # changelist form
            pass
        try:
            self.instance.preference
        except NotFoundInRegistry:
            raise ValidationError(NotFoundInRegistry.detail_default)
        return self.cleaned_data

    def save(self, *args, **kwargs):
        self.instance.value = self.cleaned_data["raw_value"]
        return super(AbstractSinglePreferenceForm, self).save(*args, **kwargs)


class SinglePerInstancePreferenceForm(AbstractSinglePreferenceForm):
    class Meta:
        fields = ("instance",) + AbstractSinglePreferenceForm.Meta.fields

    def clean(self):
        cleaned_data = super(AbstractSinglePreferenceForm, self).clean()
        try:
            self.instance.name, self.instance.section = (
                cleaned_data["name"],
                cleaned_data["section"],
            )
        except KeyError:  # changelist form
            pass
        i = cleaned_data.get("instance")
        if i:
            self.instance.instance = i
            try:
                self.instance.preference
            except NotFoundInRegistry:
                raise ValidationError(NotFoundInRegistry.detail_default)
        return self.cleaned_data


class GlobalSinglePreferenceForm(AbstractSinglePreferenceForm):
    class Meta:
        model = GlobalPreferenceModel
        fields = AbstractSinglePreferenceForm.Meta.fields


def preference_form_builder(form_base_class, preferences=[], **kwargs):
    """
    Return a form class for updating preferences
    :param form_base_class: a Form class used as the base. Must have a ``registry` attribute
    :param preferences: a list of :py:class:
    :param section: a section where the form builder will load preferences
    """
    registry = form_base_class.registry
    preferences_obj = []
    if len(preferences) > 0:
        # Preferences have been selected explicitly
        for pref in preferences:
            if isinstance(pref, str):
                preferences_obj.append(registry.get(name=pref))
            elif type(pref) == tuple:
                preferences_obj.append(registry.get(name=pref[0], section=pref[1]))
            else:
                raise NotImplementedError(
                    "The data you provide can't be converted to a Preference object"
                )
    elif kwargs.get("section", None):
        # Try to use section param
        preferences_obj = registry.preferences(section=kwargs.get("section", None))

    else:
        # display all preferences in the form
        preferences_obj = registry.preferences()

    fields = OrderedDict()
    instances = []
    if "model" in kwargs:
        # backward compat, see #212
        manager_kwargs = kwargs.get("model")
    else:
        manager_kwargs = {"instance": kwargs.get("instance", None)}
    manager = registry.manager(**manager_kwargs)

    for preference in preferences_obj:
        f = preference.field
        instance = manager.get_db_pref(
            section=preference.section.name, name=preference.name
        )
        f.initial = instance.value
        fields[preference.identifier()] = f
        instances.append(instance)

    form_class = type("Custom" + form_base_class.__name__, (form_base_class,), {})
    form_class.base_fields = fields
    form_class.preferences = preferences_obj
    form_class.instances = instances
    form_class.manager = manager
    return form_class


def global_preference_form_builder(preferences=[], **kwargs):
    """
    A shortcut :py:func:`preference_form_builder(GlobalPreferenceForm, preferences, **kwargs)`
    """
    return preference_form_builder(GlobalPreferenceForm, preferences, **kwargs)


class PreferenceForm(forms.Form):

    registry = None

    def update_preferences(self, **kwargs):
        for instance in self.instances:
            self.manager.update_db_pref(
                instance.preference.section.name,
                instance.preference.name,
                self.cleaned_data[instance.preference.identifier()],
            )


class GlobalPreferenceForm(PreferenceForm):

    registry = global_preferences_registry