-
Notifications
You must be signed in to change notification settings - Fork 29
/
models.py
115 lines (98 loc) · 4.45 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
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from pydash import get
from core.client_configs.constants import HOME_TYPE, CONFIG_TYPES, EMPTY_TABS_CONFIG, NOT_LIST_TABS_CONFIG, \
INVALID_TABS_CONFIG, ONE_DEFAULT_TAB, ASC_AND_DESC_SORT, UNSUPPORTED_SORT_ATTRIBUTE
from core.common.constants import SUPER_ADMIN_USER_ID
from core.common.utils import get_resource_class_from_resource_name
class ClientConfig(models.Model):
class Meta:
db_table = 'client_configurations'
name = models.TextField(default='View Configuration')
description = models.TextField(null=True, blank=True)
type = models.CharField(choices=CONFIG_TYPES, default=HOME_TYPE, max_length=255)
is_default = models.BooleanField(default=False)
config = models.JSONField()
resource_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
resource_id = models.PositiveIntegerField()
resource = GenericForeignKey('resource_type', 'resource_id')
public = models.BooleanField(default=True)
is_template = models.BooleanField(default=False)
created_by = models.ForeignKey(
'users.UserProfile', default=SUPER_ADMIN_USER_ID, on_delete=models.SET_DEFAULT,
related_name='%(app_label)s_%(class)s_related_created_by',
related_query_name='%(app_label)s_%(class)ss_created_by',
)
updated_by = models.ForeignKey(
'users.UserProfile', default=SUPER_ADMIN_USER_ID, on_delete=models.SET_DEFAULT,
related_name='%(app_label)s_%(class)s_related_updated_by',
related_query_name='%(app_label)s_%(class)ss_updated_by',
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
errors = None
@property
def is_home(self):
return self.type == HOME_TYPE
@property
def uri(self):
return f"/client-configs/{self.id}/"
def clean(self):
self.errors = None
super().clean()
if self.is_home:
self.validate_home_config()
if not self.errors:
self.format_home_config_tabs()
if self.errors:
raise ValidationError(self.errors)
@property
def siblings(self):
return self.__class__.objects.filter(
resource_type_id=self.resource_type_id, resource_id=self.resource_id, type=self.type
).exclude(id=self.id)
def format_home_config_tabs(self):
for tab in self.config.get('tabs', []):
fields = get(tab, 'fields')
if isinstance(fields, dict):
tab['fields'] = [{k: v} for k, v in fields.items()]
def validate_home_config(self):
self.validate_home_tabs_config()
if not self.errors:
self.validate_sort_attributes()
def validate_home_tabs_config(self):
tabs = get(self.config, 'tabs')
if not tabs:
self.errors = {'tabs': [EMPTY_TABS_CONFIG]}
elif not isinstance(tabs, list):
self.errors = {'tabs': [NOT_LIST_TABS_CONFIG]}
elif any(not isinstance(tab, dict) for tab in tabs):
self.errors = {'tabs': [INVALID_TABS_CONFIG]}
else:
default_tabs = [tab for tab in tabs if tab.get('default', False)]
if len(default_tabs) != 1:
self.errors = {'tabs': [ONE_DEFAULT_TAB]}
def validate_sort_attributes(self):
tabs = get(self.config, 'tabs', [])
for tab in tabs:
sort_asc = tab.get('sortAsc', None)
sort_desc = tab.get('sortDesc', None)
if not sort_asc and not sort_desc:
continue
if sort_asc and sort_desc:
self.errors = {'tabs': [ASC_AND_DESC_SORT]}
return
attr = sort_asc or sort_desc
if attr not in ['score'] and attr not in self.__get_resource_sortable_fields(get(tab, 'type')):
self.errors = {'tabs': [UNSUPPORTED_SORT_ATTRIBUTE]}
return
def __get_resource_sortable_fields(self, tab_type):
es_fields = self.__get_es_fields(tab_type) or {}
return [field for field, config in es_fields.items() if config.get('sortable', False)]
@staticmethod
def __get_es_fields(tab_type):
klass = get_resource_class_from_resource_name(tab_type)
return klass.es_fields if klass else None