refactor(orgs): 重构组织表结构

This commit is contained in:
xinwen
2020-07-20 10:42:22 +08:00
committed by 老广
parent 1bc913ab13
commit de3865fa1d
27 changed files with 702 additions and 299 deletions

View 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'

View File

@@ -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
View 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
View 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