diff --git a/apps/audits/utils.py b/apps/audits/utils.py index 5813c3db8..4312962e6 100644 --- a/apps/audits/utils.py +++ b/apps/audits/utils.py @@ -37,6 +37,9 @@ def _get_instance_field_value( if not include_model_fields and not getattr(f, 'primary_key', False): continue + if isinstance(f, GenericForeignKey): + continue + if isinstance(f, (models.FileField, models.ImageField)): continue diff --git a/apps/common/drf/parsers/base.py b/apps/common/drf/parsers/base.py index 6d4b70788..33b344457 100644 --- a/apps/common/drf/parsers/base.py +++ b/apps/common/drf/parsers/base.py @@ -9,7 +9,7 @@ from rest_framework import status from rest_framework.exceptions import ParseError, APIException from rest_framework.parsers import BaseParser -from common.serializers.fields import ObjectRelatedField +from common.serializers.fields import ObjectRelatedField, LabeledChoiceField from common.utils import get_logger logger = get_logger(__file__) @@ -126,6 +126,10 @@ class BaseFileParser(BaseParser): value = [self.id_name_to_obj(v) for v in value] else: value = self.id_name_to_obj(value) + elif isinstance(field, LabeledChoiceField): + value = self.id_name_to_obj(value) + if isinstance(value, dict) and value.get('pk'): + value = value.get('pk') elif isinstance(field, serializers.ListSerializer): value = [self.parse_value(field.child, v) for v in value] elif isinstance(field, serializers.Serializer): diff --git a/apps/common/drf/renders/base.py b/apps/common/drf/renders/base.py index cdc1626ff..2c1038610 100644 --- a/apps/common/drf/renders/base.py +++ b/apps/common/drf/renders/base.py @@ -105,7 +105,8 @@ class BaseFileRenderer(BaseRenderer): elif isinstance(value, bool): value = 'Yes' if value else 'No' elif isinstance(field, LabeledChoiceField): - value = value.get('value', '') + value = value or {} + value = '{}({})'.format(value.get('label'), value.get('value')) elif isinstance(field, ObjectRelatedField): if field.many: value = [self.to_id_name(v) for v in value] diff --git a/apps/labels/mixins.py b/apps/labels/mixins.py index 23fa90386..90b76f3ed 100644 --- a/apps/labels/mixins.py +++ b/apps/labels/mixins.py @@ -7,7 +7,15 @@ __all__ = ['LabeledMixin'] class LabeledMixin(models.Model): - labels = GenericRelation(LabeledResource, object_id_field='res_id', content_type_field='res_type') + _labels = GenericRelation(LabeledResource, object_id_field='res_id', content_type_field='res_type') class Meta: abstract = True + + @property + def labels(self): + return self._labels + + @labels.setter + def labels(self, value): + self._labels.set(value, bulk=False) diff --git a/apps/labels/models.py b/apps/labels/models.py index 9d06f76e3..3bf9213f5 100644 --- a/apps/labels/models.py +++ b/apps/labels/models.py @@ -20,6 +20,10 @@ class Label(JMSOrgBaseModel): def res_count(self): return self.labeled_resources.count() + @lazyproperty + def display_name(self): + return '{}:{}'.format(self.name, self.value) + def __str__(self): return '{}:{}'.format(self.name, self.value) diff --git a/apps/labels/serializers.py b/apps/labels/serializers.py index bd4d09b90..803843ad8 100644 --- a/apps/labels/serializers.py +++ b/apps/labels/serializers.py @@ -42,7 +42,7 @@ class LabeledResourceSerializer(serializers.ModelSerializer): res_type = LabeledChoiceField( choices=[], label=_("Resource type"), source='res_type_id', required=False ) - label = ObjectRelatedField(queryset=Label.objects, attrs=('name', 'value'), label=_("Label")) + label = ObjectRelatedField(queryset=Label.objects, attrs=('id', 'display_name'), label=_("Label")) resource = serializers.CharField(label=_("Resource")) class Meta: diff --git a/apps/ops/serializers/job.py b/apps/ops/serializers/job.py index 6e95a1fb9..75729f988 100644 --- a/apps/ops/serializers/job.py +++ b/apps/ops/serializers/job.py @@ -4,14 +4,13 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from assets.models import Asset -from common.serializers import ResourceLabelsMixin from common.serializers.fields import ReadableHiddenField from ops.mixin import PeriodTaskSerializerMixin from ops.models import Job, JobExecution from orgs.mixins.serializers import BulkOrgResourceModelSerializer -class JobSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin): +class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin): creator = ReadableHiddenField(default=serializers.CurrentUserDefault()) run_after_save = serializers.BooleanField(label=_("Run after save"), default=False, required=False) nodes = serializers.ListField(required=False, child=serializers.CharField()) @@ -42,7 +41,7 @@ class JobSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer, PeriodT ] fields = read_only_fields + [ "name", "instant", "type", "module", - "args", "playbook", "assets", "labels", + "args", "playbook", "assets", "runas_policy", "runas", "creator", "use_parameter_define", "parameters_define", "timeout", "chdir", "comment", "summary", diff --git a/apps/ops/serializers/playbook.py b/apps/ops/serializers/playbook.py index 2fb06d691..1ff48906a 100644 --- a/apps/ops/serializers/playbook.py +++ b/apps/ops/serializers/playbook.py @@ -2,7 +2,6 @@ import os from rest_framework import serializers -from common.serializers import ResourceLabelsMixin from common.serializers.fields import ReadableHiddenField from ops.models import Playbook from orgs.mixins.serializers import BulkOrgResourceModelSerializer @@ -13,7 +12,7 @@ def parse_playbook_name(path): return file_name.split(".")[-2] -class PlaybookSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer): +class PlaybookSerializer(BulkOrgResourceModelSerializer): creator = ReadableHiddenField(default=serializers.CurrentUserDefault()) path = serializers.FileField(required=False) @@ -28,5 +27,5 @@ class PlaybookSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer): read_only_fields = ["id", "date_created", "date_updated"] fields = read_only_fields + [ "id", 'path', "name", "comment", "creator", - 'create_method', 'vcs_url', 'labels' + 'create_method', 'vcs_url', ]