perf: 添加 JSONManyToManyFieldSerializer

pull/10327/head
ibuler 2023-04-27 14:13:40 +08:00
parent 338ab5c634
commit 90090a7fc7
3 changed files with 32 additions and 35 deletions

View File

@ -2,7 +2,7 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from acls.models.base import ActionChoices from acls.models.base import ActionChoices
from common.serializers.fields import LabeledChoiceField, ObjectRelatedField from common.serializers.fields import JSONManyToManyField, ObjectRelatedField, LabeledChoiceField
from orgs.models import Organization from orgs.models import Organization
from users.models import User from users.models import User
@ -52,25 +52,9 @@ class ACLAccountsSerializer(serializers.Serializer):
class BaseUserAssetAccountACLSerializerMixin(serializers.Serializer): class BaseUserAssetAccountACLSerializerMixin(serializers.Serializer):
users = ACLUsersSerializer(label=_('User')) users = JSONManyToManyField(label=_('User'))
assets = ACLAssestsSerializer(label=_('Asset')) assets = JSONManyToManyField(label=_('Asset'))
accounts = ACLAccountsSerializer(label=_('Account')) accounts = JSONManyToManyField(label=_('Account'))
users_username_group = serializers.ListField(
source='users.username_group', read_only=True, child=serializers.CharField(),
label=_('User (username)')
)
assets_name_group = serializers.ListField(
source='assets.name_group', read_only=True, child=serializers.CharField(),
label=_('Asset (name)')
)
assets_address_group = serializers.ListField(
source='assets.address_group', read_only=True, child=serializers.CharField(),
label=_('Asset (address)')
)
accounts_username_group = serializers.ListField(
source='accounts.username_group', read_only=True, child=serializers.CharField(),
label=_('Account (username)')
)
reviewers = ObjectRelatedField( reviewers = ObjectRelatedField(
queryset=User.objects, many=True, required=False, label=_('Reviewers') queryset=User.objects, many=True, required=False, label=_('Reviewers')
) )
@ -84,8 +68,6 @@ class BaseUserAssetAccountACLSerializerMixin(serializers.Serializer):
class Meta: class Meta:
fields_mini = ["id", "name"] fields_mini = ["id", "name"]
fields_small = fields_mini + [ fields_small = fields_mini + [
'users_username_group', 'assets_address_group', 'assets_name_group',
'accounts_username_group',
"users", "accounts", "assets", "is_active", "users", "accounts", "assets", "is_active",
"date_created", "date_updated", "priority", "date_created", "date_updated", "priority",
"action", "comment", "created_by", "org_id", "action", "comment", "created_by", "org_id",

View File

@ -429,29 +429,29 @@ class JSONManyToManyField(models.JSONField):
return name, path, args, kwargs return name, path, args, kwargs
@staticmethod @staticmethod
def _check_value(val): def check_value(val):
if not val: if not val:
return val return val
e = ValueError( e = ValueError(_(
'Invalid JSON data for JSONManyToManyField, should be like ' "Invalid JSON data for JSONManyToManyField, should be like "
'{"type": "all"} or {"type": "ids", "ids": []} ' "{'type': 'all'} or {'type': 'ids', 'ids': []} "
'or {"type": "attrs", "attrs": [{"name": "ip", "match": "exact", "value": "value"}' "or {'type': 'attrs', 'attrs': [{'name': 'ip', 'match': 'exact', 'value': 'value'}"
) ))
if not isinstance(val, dict): if not isinstance(val, dict):
raise e raise e
if val["type"] not in ["all", "ids", "attrs"]: if val["type"] not in ["all", "ids", "attrs"]:
raise e raise ValueError(_('Invalid type, should be "all", "ids" or "attrs"'))
if val["type"] == "ids": if val["type"] == "ids":
if not isinstance(val["ids"], list): if not isinstance(val["ids"], list):
raise e raise ValueError(_("Invalid ids for ids, should be a list"))
elif val["type"] == "attrs": elif val["type"] == "attrs":
if not isinstance(val["attrs"], list): if not isinstance(val["attrs"], list):
raise e raise ValueError(_("Invalid attrs, should be a list of dict"))
for attr in val["attrs"]: for attr in val["attrs"]:
if not isinstance(attr, dict): if not isinstance(attr, dict):
raise e raise ValueError(_("Invalid attrs, should be a list of dict"))
if 'name' not in attr or 'value' not in attr: if 'name' not in attr or 'value' not in attr:
raise e raise ValueError(_("Invalid attrs, should be has name and value"))
def get_db_prep_value(self, value, connection, prepared=False): def get_db_prep_value(self, value, connection, prepared=False):
return self.get_prep_value(value) return self.get_prep_value(value)
@ -461,7 +461,7 @@ class JSONManyToManyField(models.JSONField):
return None return None
if isinstance(value, RelatedManager): if isinstance(value, RelatedManager):
value = value.value value = value.value
self._check_value(value) self.check_value(value)
return json.dumps(value) return json.dumps(value)
def validate(self, value, model_instance): def validate(self, value, model_instance):

View File

@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from rest_framework.fields import ChoiceField, empty from rest_framework.fields import ChoiceField, empty
from common.db.fields import TreeChoices from common.db.fields import TreeChoices, JSONManyToManyField as ModelJSONManyToManyField
from common.local import add_encrypted_field_set from common.local import add_encrypted_field_set
from common.utils import decrypt_password from common.utils import decrypt_password
@ -20,6 +20,7 @@ __all__ = [
"TreeChoicesField", "TreeChoicesField",
"LabeledMultipleChoiceField", "LabeledMultipleChoiceField",
"PhoneField", "PhoneField",
"JSONManyToManyField"
] ]
@ -216,3 +217,17 @@ class PhoneField(serializers.CharField):
phone = phonenumbers.parse(value, 'CN') phone = phonenumbers.parse(value, 'CN')
value = {'code': '+%s' % phone.country_code, 'phone': phone.national_number} value = {'code': '+%s' % phone.country_code, 'phone': phone.national_number}
return value return value
class JSONManyToManyField(serializers.JSONField):
def to_representation(self, value):
return value.value
def to_internal_value(self, data):
if not data:
data = {}
try:
ModelJSONManyToManyField.check_value(data)
except ValueError as e:
raise serializers.ValidationError(e)
return super().to_internal_value(data)