From 6864d684aecae13e041922ca6b15435a0d651237 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Wed, 11 Mar 2020 15:43:25 +0100 Subject: [PATCH 1/3] Add extensible form which allows to add elements to django-material form layouts --- aleksis/core/forms.py | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index 0daff5fd9..cf6433bfc 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -5,15 +5,65 @@ from django import forms from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError +from django.forms.models import ModelFormMetaclass from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget from material import Layout, Fieldset, Row +from material.base import LayoutNode from .models import Group, Person, School, SchoolTerm, Announcement, AnnouncementRecipient +class ExtensibleFormMetaclass(ModelFormMetaclass): + def __new__(mcs, name, bases, dct): + x = super().__new__(mcs, name, bases, dct) + + if hasattr(x, "layout"): + base_layout = x.layout.elements + else: + base_layout = [] + + x.base_layout = base_layout + x.layout = Layout(*base_layout) + + return x + + +class ExtensibleForm(forms.ModelForm, metaclass=ExtensibleFormMetaclass): + """ Base model for extensible forms + + This mixin adds functionality which allows + - apps to add layout nodes to the layout used by django-material + + Add layout nodes + ================ + + ``` + from material import Fieldset + + from aleksis.core.forms import ExampleForm + + node = Fieldset("field_name") + ExampleForm.add_node_to_layout(node) + ``` + + """ + + @classmethod + def add_node_to_layout(cls, node: LayoutNode): + """ + Add a node to `layout` attribute + + :param node: django-material layout node (Fieldset, Row etc.) + :type node: LayoutNode + """ + + cls.base_layout.append(node) + cls.layout = Layout(*cls.base_layout) + + class PersonAccountForm(forms.ModelForm): class Meta: model = Person -- GitLab From e4e1d9b163de24032fa0d1505a4d92cc18a5e193 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Thu, 12 Mar 2020 11:08:33 +0100 Subject: [PATCH 2/3] Move ExtensibleForm to mixins.py --- aleksis/core/forms.py | 50 ------------------------------------------ aleksis/core/mixins.py | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index cf6433bfc..0daff5fd9 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -5,65 +5,15 @@ from django import forms from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError -from django.forms.models import ModelFormMetaclass from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget from material import Layout, Fieldset, Row -from material.base import LayoutNode from .models import Group, Person, School, SchoolTerm, Announcement, AnnouncementRecipient -class ExtensibleFormMetaclass(ModelFormMetaclass): - def __new__(mcs, name, bases, dct): - x = super().__new__(mcs, name, bases, dct) - - if hasattr(x, "layout"): - base_layout = x.layout.elements - else: - base_layout = [] - - x.base_layout = base_layout - x.layout = Layout(*base_layout) - - return x - - -class ExtensibleForm(forms.ModelForm, metaclass=ExtensibleFormMetaclass): - """ Base model for extensible forms - - This mixin adds functionality which allows - - apps to add layout nodes to the layout used by django-material - - Add layout nodes - ================ - - ``` - from material import Fieldset - - from aleksis.core.forms import ExampleForm - - node = Fieldset("field_name") - ExampleForm.add_node_to_layout(node) - ``` - - """ - - @classmethod - def add_node_to_layout(cls, node: LayoutNode): - """ - Add a node to `layout` attribute - - :param node: django-material layout node (Fieldset, Row etc.) - :type node: LayoutNode - """ - - cls.base_layout.append(node) - cls.layout = Layout(*cls.base_layout) - - class PersonAccountForm(forms.ModelForm): class Meta: model = Person diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index 984a41255..f921ae4e8 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -4,9 +4,11 @@ from typing import Any, Callable, Optional from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import QuerySet +from django.forms.models import ModelFormMetaclass, ModelForm from easyaudit.models import CRUDEvent from jsonstore.fields import JSONField, JSONFieldMixin +from material.base import LayoutNode, Layout class CRUDMixin(models.Model): @@ -170,3 +172,51 @@ class ExtensibleModel(CRUDMixin): class PureDjangoModel(object): """ No-op mixin to mark a model as deliberately not using ExtensibleModel """ pass + + +class ExtensibleFormMetaclass(ModelFormMetaclass): + def __new__(mcs, name, bases, dct): + x = super().__new__(mcs, name, bases, dct) + + if hasattr(x, "layout"): + base_layout = x.layout.elements + else: + base_layout = [] + + x.base_layout = base_layout + x.layout = Layout(*base_layout) + + return x + + +class ExtensibleForm(ModelForm, metaclass=ExtensibleFormMetaclass): + """ Base model for extensible forms + + This mixin adds functionality which allows + - apps to add layout nodes to the layout used by django-material + + Add layout nodes + ================ + + ``` + from material import Fieldset + + from aleksis.core.forms import ExampleForm + + node = Fieldset("field_name") + ExampleForm.add_node_to_layout(node) + ``` + + """ + + @classmethod + def add_node_to_layout(cls, node: LayoutNode): + """ + Add a node to `layout` attribute + + :param node: django-material layout node (Fieldset, Row etc.) + :type node: LayoutNode + """ + + cls.base_layout.append(node) + cls.layout = Layout(*cls.base_layout) -- GitLab From d48104e4e1df5481863a5878aad3a5a8700f4b84 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Thu, 12 Mar 2020 20:09:33 +0100 Subject: [PATCH 3/3] Make ExtensibleFormMetaclass private --- aleksis/core/mixins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index f921ae4e8..c034717c5 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -174,7 +174,7 @@ class PureDjangoModel(object): pass -class ExtensibleFormMetaclass(ModelFormMetaclass): +class _ExtensibleFormMetaclass(ModelFormMetaclass): def __new__(mcs, name, bases, dct): x = super().__new__(mcs, name, bases, dct) @@ -189,7 +189,7 @@ class ExtensibleFormMetaclass(ModelFormMetaclass): return x -class ExtensibleForm(ModelForm, metaclass=ExtensibleFormMetaclass): +class ExtensibleForm(ModelForm, metaclass=_ExtensibleFormMetaclass): """ Base model for extensible forms This mixin adds functionality which allows -- GitLab