feat: 优化工单模块

pull/5372/head
Bai 2020-12-31 18:37:55 +08:00 committed by Jiangjie.Bai
parent 167734ca5d
commit 5c483084b7
9 changed files with 346 additions and 152 deletions

View File

@ -1,13 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import copy
from collections import OrderedDict
from rest_framework.serializers import ALL_FIELDS
from rest_framework import serializers from rest_framework import serializers
import six import six
__all__ = [ __all__ = [
'StringIDField', 'StringManyToManyField', 'ChoiceDisplayField', 'StringIDField', 'StringManyToManyField', 'ChoiceDisplayField',
'CustomMetaDictField', 'ReadableHiddenField', 'CustomMetaDictField', 'ReadableHiddenField', 'JSONFieldModelSerializer'
] ]
@ -130,3 +133,184 @@ class CustomMetaDictField(serializers.DictField):
value = self.filter_value_key(dictionary, value) value = self.filter_value_key(dictionary, value)
value = self.strip_value(value) value = self.strip_value(value)
return value return value
class JSONFieldModelSerializer(serializers.Serializer):
""" Model JSONField Serializer"""
def __init__(self, *args, **kwargs):
mode_field = getattr(self.Meta, 'model_field')
if mode_field:
kwargs['label'] = mode_field.field.verbose_name
super().__init__(*args, **kwargs)
class Meta:
model = None
model_field = None
fields = None
exclude = None
def get_fields(self):
assert hasattr(self, 'Meta'), (
'Class {serializer_class} missing "Meta" attribute'.format(
serializer_class=self.__class__.__name__
)
)
assert hasattr(self.Meta, 'model'), (
'Class {serializer_class} missing "Meta.model" attribute'.format(
serializer_class=self.__class__.__name__
)
)
model_fields_mapping = {field.name: field for field in self.Meta.model._meta.fields}
assert hasattr(self.Meta, 'model_field'), (
'Class {serializer_class} missing "Meta.model_field" attribute'.format(
serializer_class=self.__class__.__name__
)
)
assert self.Meta.model_field.field.name in model_fields_mapping.keys(), (
'Class {serializer_class} "Meta.model_field" attribute not in '
'"Meta.model._meta.fields"'.format(
serializer_class=self.__class__.__name__,
)
)
declared_fields = copy.deepcopy(self._declared_fields)
read_only_field_names = self.get_read_only_field_names()
field_names = self.get_field_names(declared_fields)
fields = OrderedDict()
for field_name in field_names:
if field_name not in declared_fields:
continue
field = declared_fields[field_name]
if field_name in read_only_field_names:
setattr(field, 'read_only', True)
fields[field_name] = field
return fields
def get_field_names(self, declared_fields):
"""
Returns the list of all field names that should be created when
instantiating this serializer class. This is based on the default
set of fields, but also takes into account the `Meta.fields` or
`Meta.exclude` options if they have been specified.
"""
fields = getattr(self.Meta, 'fields', None)
exclude = getattr(self.Meta, 'exclude', None)
if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)):
raise TypeError(
'The `fields` option must be a list or tuple or "__all__". '
'Got %s.' % type(fields).__name__
)
if exclude and not isinstance(exclude, (list, tuple)):
raise TypeError(
'The `exclude` option must be a list or tuple. Got %s.' %
type(exclude).__name__
)
assert not (fields and exclude), (
"Cannot set both 'fields' and 'exclude' options on "
"serializer {serializer_class}.".format(
serializer_class=self.__class__.__name__
)
)
assert not (fields is None and exclude is None), (
"Creating a ModelSerializer without either the 'fields' attribute "
"or the 'exclude' attribute has been deprecated since 3.3.0, "
"and is now disallowed. Add an explicit fields = '__all__' to the "
"{serializer_class} serializer.".format(
serializer_class=self.__class__.__name__
),
)
if fields == ALL_FIELDS:
fields = None
if fields is not None:
# Ensure that all declared fields have also been included in the
# `Meta.fields` option.
# Do not require any fields that are declared in a parent class,
# in order to allow serializer subclasses to only include
# a subset of fields.
required_field_names = set(declared_fields)
for cls in self.__class__.__bases__:
required_field_names -= set(getattr(cls, '_declared_fields', []))
for field_name in required_field_names:
assert field_name in fields, (
"The field '{field_name}' was declared on serializer "
"{serializer_class}, but has not been included in the "
"'fields' option.".format(
field_name=field_name,
serializer_class=self.__class__.__name__
)
)
return fields
# Use the default set of field names if `Meta.fields` is not specified.
fields = self.get_default_field_names(declared_fields)
if exclude is not None:
# If `Meta.exclude` is included, then remove those fields.
for field_name in exclude:
assert field_name not in self._declared_fields, (
"Cannot both declare the field '{field_name}' and include "
"it in the {serializer_class} 'exclude' option. Remove the "
"field or, if inherited from a parent serializer, disable "
"with `{field_name} = None`."
.format(
field_name=field_name,
serializer_class=self.__class__.__name__
)
)
assert field_name in fields, (
"The field '{field_name}' was included on serializer "
"{serializer_class} in the 'exclude' option, but does "
"not match any model field.".format(
field_name=field_name,
serializer_class=self.__class__.__name__
)
)
fields.remove(field_name)
return fields
@staticmethod
def get_default_field_names(declared_fields):
return declared_fields
def get_read_only_field_names(self):
read_only_fields = getattr(self.Meta, 'read_only_fields', None)
if read_only_fields is not None:
if not isinstance(read_only_fields, (list, tuple)):
raise TypeError(
'The `read_only_fields` option must be a list or tuple. '
'Got %s.' % type(read_only_fields).__name__
)
return read_only_fields
def to_internal_value(self, data):
return super().to_internal_value(data)
def to_representation(self, instance):
if not isinstance(instance, dict):
return super().to_representation(instance)
for field_name, field in self.fields.items():
if field_name in instance:
continue
if field.allow_null:
continue
setattr(field, 'allow_null', True)
return super().to_representation(instance)

View File

@ -56,7 +56,7 @@ class GenericSerializerMixin:
return serializer_class return serializer_class
class JSONFieldsSerializerMixin: class JSONFieldsModelSerializerMixin:
""" """
作用: 获取包含 JSONField 字段的序列类 作用: 获取包含 JSONField 字段的序列类
@ -76,31 +76,20 @@ class JSONFieldsSerializerMixin:
'json_field_1': { 'json_field_1': {
'type': { 'type': {
'apply_asset': { 'apply_asset': {
'get': { 'get': TestSerializer,
'class': TestSerializer, 'post': TestSerializer,
'attrs': {'required': True}, 'open':TestSerializer,
}, 'approve': TestSerializer,
'post': {
'class': TestSerializer,
'attrs': {'required': True}
},
'open': {
'class': TestSerializer,
'attrs': {'required': False}
},
'approve': {
'class': TestSerializer,
},
}, },
'apply_application': { 'apply_application': {
'get': {}, 'get': TestSerializer,
'post': {}, 'post': TestSerializer,
'put': {}, 'put': TestSerializer,
}, },
'login_confirm': { 'login_confirm': {
'get': {}, 'get': TestSerializer,
'post': {}, 'post': TestSerializer,
'put': {}, 'put': TestSerializer,
} }
}, },
'category': {} 'category': {}
@ -113,19 +102,13 @@ class JSONFieldsSerializerMixin:
json_fields_category_mapping = {} json_fields_category_mapping = {}
json_fields_serializer_classes = None json_fields_serializer_classes = None
@lazyproperty # 保存当前处理的JSONField名称
def default_json_field_serializer(self): __field = None
class DefaultJSONFieldSerializer(serializers.JSONField): serializer_class = None
pass
if self.action in ['get', 'list', 'retrieve']:
attrs = {'readonly': False}
else:
attrs = {'readonly': True}
return DefaultJSONFieldSerializer(attrs)
def get_json_field_query_category(self, field, category): def get_json_field_query_category(self, category):
query_category = self.request.query_params.get(category) query_category = self.request.query_params.get(category)
category_choices = self.json_fields_category_mapping[field][category] category_choices = self.json_fields_category_mapping[self.__field][category]
if query_category and query_category not in category_choices: if query_category and query_category not in category_choices:
error = _( error = _(
'Please bring the query parameter `{}`, ' 'Please bring the query parameter `{}`, '
@ -135,56 +118,57 @@ class JSONFieldsSerializerMixin:
raise JMSException({'query_params_error': error}) raise JMSException({'query_params_error': error})
return query_category return query_category
def get_json_field_serializer_classes_by_query_category(self, field): def get_json_field_action_serializer_classes_by_query_category(self):
serializer_classes = None action_serializer_classes = None
category_collection = self.json_fields_category_mapping[field] category_collection = self.json_fields_category_mapping[self.__field]
for category in category_collection: for category in category_collection:
query_category = self.get_json_field_query_category(field, category) category_value = self.get_json_field_query_category(category)
if not query_category: if not category_value:
continue continue
category_serializer_classes = self.json_fields_serializer_classes[field][category] category_serializer_classes = self.json_fields_serializer_classes[self.__field][category]
if query_category not in category_serializer_classes.keys(): action_serializer_classes = category_serializer_classes.get(category_value)
continue if action_serializer_classes:
serializer_classes = category_serializer_classes[query_category] break
return action_serializer_classes
def get_json_field_action_serializer_classes(self):
category_collection = self.json_fields_category_mapping[self.__field]
if category_collection:
serializer_classes = self.get_json_field_action_serializer_classes_by_query_category()
else:
serializer_classes = self.json_fields_serializer_classes[self.__field]
return serializer_classes return serializer_classes
def get_json_field_serializer_info_by_view_action(self, serializer_classes): def get_json_field_serializer_class_by_action(self, serializer_classes):
if serializer_classes is None:
return None
if self.action in ['metadata']: if self.action in ['metadata']:
action = self.request.query_params.get('action') action = self.request.query_params.get('action')
if not action: if not action:
raise JMSException('The `metadata` methods must carry query parameter `action`') raise JMSException('The `metadata` methods must carry query parameter `action`')
else: else:
action = self.action action = self.action
serializer_info = serializer_classes.get(action) serializer_class = serializer_classes.get(action)
return serializer_info return serializer_class
def get_json_field_serializer_info(self, field): @lazyproperty
category_collection = self.json_fields_category_mapping[field] def default_json_field_serializer_class(self):
if category_collection: readonly_json_field_serializer_class = type(
serializer_classes = self.get_json_field_serializer_classes_by_query_category(field) 'DefaultReadonlyJSONFieldSerializer', (serializers.JSONField,),
else: )
serializer_classes = self.json_fields_serializer_classes[field] return readonly_json_field_serializer_class
if not serializer_classes: def get_json_field_serializer(self):
return None serializer_classes = self.get_json_field_action_serializer_classes()
serializer_class = self.get_json_field_serializer_class_by_action(serializer_classes)
serializer_info = self.get_json_field_serializer_info_by_view_action(serializer_classes) if serializer_class:
return serializer_info serializer = serializer_class()
return serializer
@staticmethod serializer_class = serializer_classes.get('default')
def new_json_field_serializer(class_info): if serializer_class:
serializer_class = class_info['class'] serializer = serializer_class(**{'read_only': True})
serializer_attrs = class_info.get('attrs', {}) return serializer
serializer = serializer_class(serializer_attrs) return self.default_json_field_serializer_class(**{'read_only': True})
return serializer
def get_json_field_serializer(self, field):
serializer_info = self.get_json_field_serializer_info(field)
if not serializer_info:
return None
serializer = self.new_json_field_serializer(serializer_info)
return serializer
def get_json_fields_serializer_mapping(self): def get_json_fields_serializer_mapping(self):
""" """
@ -196,14 +180,12 @@ class JSONFieldsSerializerMixin:
fields_serializer_mapping = {} fields_serializer_mapping = {}
fields = self.json_fields_serializer_classes.keys() fields = self.json_fields_serializer_classes.keys()
for field in fields: for field in fields:
serializer = self.get_json_field_serializer(field) self.__field = field
if serializer is None: serializer = self.get_json_field_serializer()
serializer = self.default_json_field_serializer fields_serializer_mapping[self.__field] = serializer
fields_serializer_mapping[field] = serializer
return fields_serializer_mapping return fields_serializer_mapping
@staticmethod def build_include_json_fields_serializer_class(self, base, attrs):
def new_include_json_fields_serializer_class(base, attrs):
serializer_class_name = ''.join([ serializer_class_name = ''.join([
field_serializer.__class__.__name__ for field_serializer in attrs.values() field_serializer.__class__.__name__ for field_serializer in attrs.values()
]) ])
@ -217,13 +199,13 @@ class JSONFieldsSerializerMixin:
fields_serializer_mapping = self.get_json_fields_serializer_mapping() fields_serializer_mapping = self.get_json_fields_serializer_mapping()
if not fields_serializer_mapping: if not fields_serializer_mapping:
return serializer_class return serializer_class
serializer_class = self.new_include_json_fields_serializer_class( serializer_class = self.build_include_json_fields_serializer_class(
base=serializer_class, attrs=fields_serializer_mapping base=serializer_class, attrs=fields_serializer_mapping
) )
return serializer_class return serializer_class
class SerializerMixin(JSONFieldsSerializerMixin, GenericSerializerMixin): class SerializerMixin(JSONFieldsModelSerializerMixin, GenericSerializerMixin):
pass pass

View File

@ -1,11 +1,10 @@
from common.exceptions import JMSException
from tickets import const, serializers from tickets import const, serializers
__all__ = ['TicketJSONFieldsSerializerViewMixin'] __all__ = ['TicketJSONFieldsModelSerializerViewMixin']
class TicketJSONFieldsSerializerViewMixin: class TicketJSONFieldsModelSerializerViewMixin:
json_fields_category_mapping = { json_fields_category_mapping = {
'meta': { 'meta': {
'type': const.TicketTypeChoices.values, 'type': const.TicketTypeChoices.values,
@ -15,30 +14,18 @@ class TicketJSONFieldsSerializerViewMixin:
'meta': { 'meta': {
'type': { 'type': {
const.TicketTypeChoices.apply_asset.value: { const.TicketTypeChoices.apply_asset.value: {
'open': { 'default': serializers.TicketMetaApplyAssetSerializer,
'class': serializers.TicketMetaApplyAssetApplySerializer, 'open': serializers.TicketMetaApplyAssetApplySerializer,
'attrs': {'required': True} 'approve': serializers.TicketMetaApplyAssetApproveSerializer
},
'approve': {
'class': serializers.TicketMetaApplyAssetApproveSerializer,
'attrs': {'required': True}
}
}, },
const.TicketTypeChoices.apply_application.value: { const.TicketTypeChoices.apply_application.value: {
'open': { 'default': serializers.TicketMetaApplyApplicationSerializer,
'class': serializers.TicketMetaApplyApplicationApplySerializer, 'open': serializers.TicketMetaApplyApplicationApplySerializer,
'attrs': {'required': True} 'approve': serializers.TicketMetaApplyApplicationApproveSerializer,
},
'approve': {
'class': serializers.TicketMetaApplyApplicationApproveSerializer,
'attrs': {'required': True}
}
}, },
const.TicketTypeChoices.login_confirm.value: { const.TicketTypeChoices.login_confirm.value: {
'open': { 'default': serializers.TicketMetaLoginConfirmSerializer,
'class': serializers.TicketMetaLoginConfirmApplySerializer, 'open': serializers.TicketMetaLoginConfirmApplySerializer
'attrs': {'required': True}
}
} }
} }
} }

View File

@ -11,13 +11,13 @@ from common.const.http import POST, PUT
from tickets import serializers from tickets import serializers
from tickets.permissions.ticket import IsAssignee, NotClosed from tickets.permissions.ticket import IsAssignee, NotClosed
from tickets.models import Ticket from tickets.models import Ticket
from tickets.api.ticket.mixin import TicketJSONFieldsSerializerViewMixin from tickets.api.ticket.mixin import TicketJSONFieldsModelSerializerViewMixin
__all__ = ['TicketViewSet'] __all__ = ['TicketViewSet']
class TicketViewSet(TicketJSONFieldsSerializerViewMixin, CommonApiMixin, viewsets.ModelViewSet): class TicketViewSet(TicketJSONFieldsModelSerializerViewMixin, CommonApiMixin, viewsets.ModelViewSet):
permission_classes = (IsValidUser,) permission_classes = (IsValidUser,)
serializer_class = serializers.TicketSerializer serializer_class = serializers.TicketSerializer
serializer_classes = { serializer_classes = {

View File

@ -3,15 +3,18 @@ from django.utils.translation import ugettext_lazy as _
from applications.models import Category, Application from applications.models import Category, Application
from assets.models import SystemUser from assets.models import SystemUser
from .base import BaseTicketMetaSerializer, BaseTicketMetaApproveSerializerMixin from .base import BaseTicketMetaApproveSerializerMixin
from common.fields.serializer import JSONFieldModelSerializer
from tickets.models import Ticket
__all__ = [ __all__ = [
'TicketMetaApplyApplicationSerializer',
'TicketMetaApplyApplicationApplySerializer', 'TicketMetaApplyApplicationApplySerializer',
'TicketMetaApplyApplicationApproveSerializer', 'TicketMetaApplyApplicationApproveSerializer',
] ]
class TicketMetaApplyApplicationSerializer(BaseTicketMetaSerializer): class TicketMetaApplyApplicationSerializer(JSONFieldModelSerializer):
# 申请信息 # 申请信息
apply_category = serializers.ChoiceField( apply_category = serializers.ChoiceField(
required=True, choices=Category.choices, label=_('Category') required=True, choices=Category.choices, label=_('Category')
@ -63,16 +66,33 @@ class TicketMetaApplyApplicationSerializer(BaseTicketMetaSerializer):
required=True, label=_('Date expired') required=True, label=_('Date expired')
) )
class TicketMetaApplyApplicationApplySerializer(TicketMetaApplyApplicationSerializer):
class Meta: class Meta:
model = Ticket
model_field = Ticket.meta
fields = [ fields = [
'apply_category', 'apply_category_display', 'apply_category', 'apply_category_display',
'apply_type', 'apply_type_display', 'apply_type', 'apply_type_display',
'apply_application_group', 'apply_system_user_group', 'apply_application_group', 'apply_system_user_group',
'apply_date_start', 'apply_date_expired', 'apply_date_start', 'apply_date_expired',
'approve_applications', 'approve_applications_snapshot',
'approve_system_users', 'approve_system_users_snapshot',
'approve_date_start', 'approve_date_expired'
] ]
read_only_fields = fields
class TicketMetaApplyApplicationApplySerializer(TicketMetaApplyApplicationSerializer):
class Meta(TicketMetaApplyApplicationSerializer.Meta):
required_fields = [
'apply_category', 'apply_type',
'apply_application_group', 'apply_system_user_group',
'apply_date_start', 'apply_date_expired',
]
read_only_fields = list(
set(TicketMetaApplyApplicationSerializer.Meta.fields) - set(required_fields)
)
def validate_apply_type(self, tp): def validate_apply_type(self, tp):
category = self.root.initial_data['meta'].get('apply_category') category = self.root.initial_data['meta'].get('apply_category')
@ -89,11 +109,13 @@ class TicketMetaApplyApplicationApproveSerializer(BaseTicketMetaApproveSerialize
TicketMetaApplyApplicationSerializer): TicketMetaApplyApplicationSerializer):
class Meta: class Meta:
fields = { required_fields = {
'approve_applications', 'approve_applications_snapshot', 'approve_applications', 'approve_system_users',
'approve_system_users', 'approve_system_users_snapshot',
'approve_date_start', 'approve_date_expired' 'approve_date_start', 'approve_date_expired'
} }
read_only_fields = list(
set(TicketMetaApplyApplicationSerializer.Meta.fields) - set(required_fields)
)
def validate_approve_applications(self, approve_applications): def validate_approve_applications(self, approve_applications):
application_type = self.root.instance.meta['apply_type'] application_type = self.root.instance.meta['apply_type']

View File

@ -2,16 +2,20 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from perms.serializers import ActionsField from perms.serializers import ActionsField
from assets.models import Asset, SystemUser from assets.models import Asset, SystemUser
from .base import BaseTicketMetaSerializer, BaseTicketMetaApproveSerializerMixin from .base import BaseTicketMetaApproveSerializerMixin
from tickets.models import Ticket
from common.fields.serializer import JSONFieldModelSerializer
__all__ = [ __all__ = [
'TicketMetaApplyAssetSerializer',
'TicketMetaApplyAssetApplySerializer', 'TicketMetaApplyAssetApplySerializer',
'TicketMetaApplyAssetApproveSerializer', 'TicketMetaApplyAssetApproveSerializer',
] ]
class TicketMetaApplyAssetSerializer(BaseTicketMetaSerializer): class TicketMetaApplyAssetSerializer(JSONFieldModelSerializer):
# 申请信息 # 申请信息
apply_ip_group = serializers.ListField( apply_ip_group = serializers.ListField(
required=False, child=serializers.IPAddressField(), label=_('IP group'), required=False, child=serializers.IPAddressField(), label=_('IP group'),
@ -71,28 +75,46 @@ class TicketMetaApplyAssetSerializer(BaseTicketMetaSerializer):
required=True, label=_('Date expired') required=True, label=_('Date expired')
) )
class TicketMetaApplyAssetApplySerializer(TicketMetaApplyAssetSerializer):
class Meta: class Meta:
model = Ticket
model_field = Ticket.meta
fields = [ fields = [
'apply_ip_group', 'apply_ip_group',
'apply_hostname_group', 'apply_system_user_group', 'apply_hostname_group', 'apply_system_user_group',
'apply_actions', 'apply_actions_display', 'apply_actions', 'apply_actions_display',
'apply_date_start', 'apply_date_expired', 'apply_date_start', 'apply_date_expired',
]
class TicketMetaApplyAssetApproveSerializer(BaseTicketMetaApproveSerializerMixin,
TicketMetaApplyAssetSerializer):
class Meta:
fields = [
'approve_assets', 'approve_assets_snapshot', 'approve_assets', 'approve_assets_snapshot',
'approve_system_users', 'approve_system_users_snapshot', 'approve_system_users', 'approve_system_users_snapshot',
'approve_actions', 'approve_actions_display', 'approve_actions', 'approve_actions_display',
'approve_date_start', 'approve_date_expired', 'approve_date_start', 'approve_date_expired',
] ]
read_only_fields = fields
class TicketMetaApplyAssetApplySerializer(TicketMetaApplyAssetSerializer):
class Meta(TicketMetaApplyAssetSerializer.Meta):
required_fields = [
'apply_ip_group', 'apply_hostname_group', 'apply_system_user_group',
'apply_actions', 'apply_date_start', 'apply_date_expired',
]
read_only_fields = list(
set(TicketMetaApplyAssetSerializer.Meta.fields) - set(required_fields)
)
class TicketMetaApplyAssetApproveSerializer(BaseTicketMetaApproveSerializerMixin,
TicketMetaApplyAssetSerializer):
class Meta(TicketMetaApplyAssetSerializer.Meta):
required_fields = [
'approve_assets', 'approve_system_users', 'approve_actions',
'approve_date_start', 'approve_date_expired',
]
read_only_fields = list(
set(TicketMetaApplyAssetSerializer.Meta.fields) - set(required_fields)
)
def validate_approve_assets(self, approve_assets): def validate_approve_assets(self, approve_assets):
assets_id = self.filter_approve_resources(resource_model=Asset, resources_id=approve_assets) assets_id = self.filter_approve_resources(resource_model=Asset, resources_id=approve_assets)

View File

@ -1,29 +1,13 @@
import copy
from collections import OrderedDict from collections import OrderedDict
from rest_framework import serializers from rest_framework import serializers
from rest_framework.serializers import ALL_FIELDS
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.utils import tmp_to_org from orgs.utils import tmp_to_org
from assets.models import SystemUser from assets.models import SystemUser
class BaseTicketMetaSerializer(serializers.Serializer):
class Meta:
fields = '__all__'
def get_fields(self):
fields = super().get_fields()
required_fields = self.Meta.fields
if required_fields == '__all__':
return fields
fields = OrderedDict({
field_name: fields.pop(field_name) for field_name in set(required_fields)
if field_name in fields.keys()
})
return fields
class BaseTicketMetaApproveSerializerMixin: class BaseTicketMetaApproveSerializerMixin:
def _filter_approve_resources_by_org(self, model, resources_id): def _filter_approve_resources_by_org(self, model, resources_id):

View File

@ -1,14 +1,15 @@
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .base import BaseTicketMetaSerializer from common.fields.serializer import JSONFieldModelSerializer
from tickets.models import Ticket
__all__ = [ __all__ = [
'TicketMetaLoginConfirmApplySerializer', 'TicketMetaLoginConfirmSerializer', 'TicketMetaLoginConfirmApplySerializer',
] ]
class TicketMetaLoginConfirmSerializer(BaseTicketMetaSerializer): class TicketMetaLoginConfirmSerializer(JSONFieldModelSerializer):
apply_login_ip = serializers.IPAddressField( apply_login_ip = serializers.IPAddressField(
required=True, label=_('Login ip') required=True, label=_('Login ip')
) )
@ -19,6 +20,21 @@ class TicketMetaLoginConfirmSerializer(BaseTicketMetaSerializer):
required=True, label=_('Login datetime') required=True, label=_('Login datetime')
) )
class Meta:
model = Ticket
model_field = Ticket.meta
fields = [
'apply_login_ip', 'apply_login_city', 'apply_login_datetime'
]
read_only_fields = fields
class TicketMetaLoginConfirmApplySerializer(TicketMetaLoginConfirmSerializer): class TicketMetaLoginConfirmApplySerializer(TicketMetaLoginConfirmSerializer):
pass
class Meta(TicketMetaLoginConfirmSerializer.Meta):
required_fields = [
'apply_login_ip', 'apply_login_city', 'apply_login_datetime'
]
read_only_fields = list(
set(TicketMetaLoginConfirmSerializer.Meta.fields) - set(required_fields)
)

View File

@ -92,8 +92,7 @@ class TicketApplySerializer(TicketActionSerializer):
raise serializers.ValidationError(error) raise serializers.ValidationError(error)
return valid_assignees return valid_assignees
@staticmethod def validate_action(self, action):
def validate_action(action):
return const.TicketActionChoices.open.value return const.TicketActionChoices.open.value
@ -123,15 +122,13 @@ class TicketApproveSerializer(TicketProcessSerializer):
class TicketRejectSerializer(TicketProcessSerializer): class TicketRejectSerializer(TicketProcessSerializer):
@staticmethod def validate_action(self, action):
def validate_action(action):
return const.TicketActionChoices.reject.value return const.TicketActionChoices.reject.value
class TicketCloseSerializer(TicketProcessSerializer): class TicketCloseSerializer(TicketProcessSerializer):
@staticmethod def validate_action(self, action):
def validate_action(action):
return const.TicketActionChoices.close.value return const.TicketActionChoices.close.value