diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index cf6433bfcac5be86d8d3e9c7d93673fa9631dc89..0daff5fd91fe2c45452025dd4d1e99bb7246953e 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 984a412556b69a71c5ce875f927989263ffce228..f921ae4e85633a0b4f0ec85bf326293f5bcaf67b 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)