-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathmodels.py
144 lines (113 loc) · 5.69 KB
/
models.py
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
import uuid
from cms.models import CMSPlugin
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.utils.html import conditional_escape, mark_safe
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _
from djangocms_frontend.fields import TagTypeField
from djangocms_frontend.settings import FRAMEWORK_PLUGIN_INFO
class AbstractFrontendUIItem(CMSPlugin):
"""
The `AbstractFrontendUIItem` class is an abstract base class that provides common functionality
for frontend UI items in a CMS plugin. It is a subclass of `CMSPlugin` class.
Use this class as a base class for custom plugins that add their own database fields.
Attributes:
- ui_item: A CharField that represents the UI item name (max length 30).
- tag_type: A TagTypeField (custom field) that represents the type of HTML tag for the UI item.
- config: A JSONField that stores additional configuration for the UI item.
Methods:
- __init__(*args, **kwargs): Constructor method that initializes the object and sets additional classes.
- __getattr__(item): Allows properties of the plugin config to be accessed as plugin properties.
- __str__(): Returns a string representation of the UI item.
- add_classes(*args): Adds additional classes to the UI item.
- add_attribute(attr, value=None): Adds an attribute to the configuration attributes.
- get_attributes(): Returns the attributes as a string for rendering the UI item.
- save(*args, **kwargs): Saves the UI item to the database.
- initialize_from_form(form=None): Populates the config JSON field based on initial values from a form.
- get_short_description(): Returns a plugin-specific short description.
- framework_info: Returns the framework information for the UI item.
Note: This is an abstract base class and should not be used directly.
"""
class Meta:
abstract = True
verbose_name = _("UI item")
ui_item = models.CharField(max_length=30)
tag_type = TagTypeField(blank=True)
config = models.JSONField(default=dict, encoder=DjangoJSONEncoder)
def __init__(self, *args, **kwargs):
self._additional_classes = []
self.uuid = str(uuid.uuid4())
super().__init__(*args, **kwargs)
def __getattr__(self, item):
"""Makes properties of plugin config available as plugin properties."""
if item[0] != "_" and item in self.config: # Avoid infinite recursion trying to get .config from db
return self.config[item]
return super().__getattribute__(item)
def __str__(self):
if "__str__" in self.config:
return self.config["__str__"]
return f"{gettext(self.ui_item)} ({str(self.pk)})"
def add_classes(self, *args):
for arg in args:
if arg:
self._additional_classes += arg.split() if isinstance(arg, str) else arg
def add_attribute(self, attr, value=None):
attrs = self.config.get("attributes", {})
if attr == "style" and attr in attrs:
value += attrs[attr]
attrs.update({attr: value})
self.config["attributes"] = attrs
def get_attributes(self):
attributes = self.config.get("attributes", {})
classes = self.get_classes() # get classes
classes = (f'class="{classes}"') if classes else "" # to string
parts = (
f'{item}="{conditional_escape(value)}"' if value else f"{item}"
for item, value in attributes.items()
if item != "class"
)
attributes_string = (classes + " ".join(parts)).strip()
return mark_safe(" " + attributes_string) if attributes_string else ""
def get_classes(self):
attributes = self.config.get("attributes", {})
classes = set(attributes.get("class", "").split()) # classes added in attriutes
classes.update(self._additional_classes) # add additional classes
return conditional_escape(" ".join(classes))
def save(self, *args, **kwargs):
self.ui_item = self.__class__.__name__
return super().save(*args, **kwargs)
def initialize_from_form(self, form=None):
"""Populates the config JSON field based on initial values provided by the fields of form"""
if form is None:
form = self.get_plugin_class().form
if isinstance(form, type): # if is class
if not getattr(form._meta, "model", None):
form._meta.model = self.__class__
form = form() # instantiate
entangled_fields = getattr(getattr(form, "_meta", None), "entangled_fields", {}).get("config", ())
for field in entangled_fields:
self.config.setdefault(field, {} if field == "attributes" else form[field].initial or "")
return self
def get_short_description(self):
"""Plugin-specific short description (to be defined by subclasses). Try title attribute first."""
return self.config.get("title", "")
@property
def framework_info(self):
return FRAMEWORK_PLUGIN_INFO.get(self.__class__.__name__, None)
class FrontendUIItem(AbstractFrontendUIItem):
"""
Class: FrontendUIItem
Inherits From: AbstractFrontendUIItem
Description:
This class represents a UI item in the frontend. It is used to define the behavior and attributes
of a UI item in the user interface.
Use this class as a base class for custom plugins that do not add their own database fields but
use the entangled form fields instead.
Attributes:
- verbose_name (str): The verbose name of the UI item.
Methods:
None
"""
class Meta:
verbose_name = _("UI item")