mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-09-24 21:08:30 +00:00
refactor(orgs): 重构组织表结构
This commit is contained in:
8
apps/common/const/choices.py
Normal file
8
apps/common/const/choices.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.db.models import ChoiceSet
|
||||
|
||||
|
||||
ADMIN = 'Admin'
|
||||
USER = 'User'
|
||||
AUDITOR = 'Auditor'
|
@@ -3,10 +3,10 @@ from django.db.models import Aggregate
|
||||
|
||||
class GroupConcat(Aggregate):
|
||||
function = 'GROUP_CONCAT'
|
||||
template = '%(function)s(%(distinct)s %(expressions)s %(order_by)s %(separator))'
|
||||
template = '%(function)s(%(expressions)s %(order_by)s %(separator)s)'
|
||||
allow_distinct = False
|
||||
|
||||
def __init__(self, expression, distinct=False, order_by=None, separator=',', **extra):
|
||||
def __init__(self, expression, order_by=None, separator=',', **extra):
|
||||
order_by_clause = ''
|
||||
if order_by is not None:
|
||||
order = 'ASC'
|
||||
@@ -21,8 +21,7 @@ class GroupConcat(Aggregate):
|
||||
|
||||
super().__init__(
|
||||
expression,
|
||||
distinct='DISTINCT' if distinct else '',
|
||||
order_by=order_by_clause,
|
||||
separator=f'SEPARATOR {separator}',
|
||||
separator=f"SEPARATOR '{separator}'",
|
||||
**extra
|
||||
)
|
||||
|
48
apps/common/db/models.py
Normal file
48
apps/common/db/models.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from functools import partial
|
||||
|
||||
|
||||
class Choice(str):
|
||||
def __new__(cls, value, label):
|
||||
self = super().__new__(cls, value)
|
||||
self.label = label
|
||||
return self
|
||||
|
||||
|
||||
class ChoiceSetType(type):
|
||||
def __new__(cls, name, bases, attrs):
|
||||
_choices = []
|
||||
collected = set()
|
||||
new_attrs = {}
|
||||
for k, v in attrs.items():
|
||||
if isinstance(v, tuple):
|
||||
v = Choice(*v)
|
||||
assert v not in collected, 'Cannot be defined repeatedly'
|
||||
_choices.append(v)
|
||||
collected.add(v)
|
||||
new_attrs[k] = v
|
||||
for base in bases:
|
||||
if hasattr(base, '_choices'):
|
||||
for c in base._choices:
|
||||
if c not in collected:
|
||||
_choices.append(c)
|
||||
collected.add(c)
|
||||
new_attrs['_choices'] = _choices
|
||||
new_attrs['_choices_dict'] = {c: c.label for c in _choices}
|
||||
return type.__new__(cls, name, bases, new_attrs)
|
||||
|
||||
def __contains__(self, item):
|
||||
return self._choices_dict.__contains__(item)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self._choices_dict.__getitem__(item)
|
||||
|
||||
def get(self, item, default=None):
|
||||
return self._choices_dict.get(item, default=None)
|
||||
|
||||
@property
|
||||
def choices(self):
|
||||
return [(c, c.label) for c in self._choices]
|
||||
|
||||
|
||||
class ChoiceSet(metaclass=ChoiceSetType):
|
||||
choices = None # 用于 Django Model 中的 choices 配置, 为了代码提示在此声明
|
43
apps/common/drf/fields.py
Normal file
43
apps/common/drf/fields.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from uuid import UUID
|
||||
|
||||
from rest_framework.fields import get_attribute
|
||||
from rest_framework.relations import ManyRelatedField, PrimaryKeyRelatedField, MANY_RELATION_KWARGS
|
||||
|
||||
|
||||
class GroupConcatedManyRelatedField(ManyRelatedField):
|
||||
def get_attribute(self, instance):
|
||||
if hasattr(instance, 'pk') and instance.pk is None:
|
||||
return []
|
||||
|
||||
attr = self.source_attrs[-1]
|
||||
|
||||
# `gc` 是 `GroupConcat` 的缩写
|
||||
gc_attr = f'gc_{attr}'
|
||||
if hasattr(instance, gc_attr):
|
||||
gc_value = getattr(instance, gc_attr)
|
||||
if isinstance(gc_value, str):
|
||||
return [UUID(pk) for pk in set(gc_value.split(','))]
|
||||
else:
|
||||
return ''
|
||||
|
||||
relationship = get_attribute(instance, self.source_attrs)
|
||||
return relationship.all() if hasattr(relationship, 'all') else relationship
|
||||
|
||||
|
||||
class GroupConcatedPrimaryKeyRelatedField(PrimaryKeyRelatedField):
|
||||
@classmethod
|
||||
def many_init(cls, *args, **kwargs):
|
||||
list_kwargs = {'child_relation': cls(*args, **kwargs)}
|
||||
for key in kwargs:
|
||||
if key in MANY_RELATION_KWARGS:
|
||||
list_kwargs[key] = kwargs[key]
|
||||
return GroupConcatedManyRelatedField(**list_kwargs)
|
||||
|
||||
def to_representation(self, value):
|
||||
if self.pk_field is not None:
|
||||
return self.pk_field.to_representation(value.pk)
|
||||
|
||||
if hasattr(value, 'pk'):
|
||||
return value.pk
|
||||
else:
|
||||
return value
|
Reference in New Issue
Block a user