Migrating custom fields serializer
parent
81454426f9
commit
6e3eeb7cca
|
@ -32,6 +32,7 @@ from taiga.projects.occ.mixins import OCCResourceMixin
|
|||
|
||||
from . import models
|
||||
from . import serializers
|
||||
from . import validators
|
||||
from . import permissions
|
||||
from . import services
|
||||
|
||||
|
@ -43,6 +44,7 @@ from . import services
|
|||
class UserStoryCustomAttributeViewSet(BulkUpdateOrderMixin, BlockedByProjectMixin, ModelCrudViewSet):
|
||||
model = models.UserStoryCustomAttribute
|
||||
serializer_class = serializers.UserStoryCustomAttributeSerializer
|
||||
validator_class = validators.UserStoryCustomAttributeValidator
|
||||
permission_classes = (permissions.UserStoryCustomAttributePermission,)
|
||||
filter_backends = (filters.CanViewProjectFilterBackend,)
|
||||
filter_fields = ("project",)
|
||||
|
@ -54,6 +56,7 @@ class UserStoryCustomAttributeViewSet(BulkUpdateOrderMixin, BlockedByProjectMixi
|
|||
class TaskCustomAttributeViewSet(BulkUpdateOrderMixin, BlockedByProjectMixin, ModelCrudViewSet):
|
||||
model = models.TaskCustomAttribute
|
||||
serializer_class = serializers.TaskCustomAttributeSerializer
|
||||
validator_class = validators.TaskCustomAttributeValidator
|
||||
permission_classes = (permissions.TaskCustomAttributePermission,)
|
||||
filter_backends = (filters.CanViewProjectFilterBackend,)
|
||||
filter_fields = ("project",)
|
||||
|
@ -65,6 +68,7 @@ class TaskCustomAttributeViewSet(BulkUpdateOrderMixin, BlockedByProjectMixin, Mo
|
|||
class IssueCustomAttributeViewSet(BulkUpdateOrderMixin, BlockedByProjectMixin, ModelCrudViewSet):
|
||||
model = models.IssueCustomAttribute
|
||||
serializer_class = serializers.IssueCustomAttributeSerializer
|
||||
validator_class = validators.IssueCustomAttributeValidator
|
||||
permission_classes = (permissions.IssueCustomAttributePermission,)
|
||||
filter_backends = (filters.CanViewProjectFilterBackend,)
|
||||
filter_fields = ("project",)
|
||||
|
@ -86,6 +90,7 @@ class BaseCustomAttributesValuesViewSet(OCCResourceMixin, HistoryResourceMixin,
|
|||
class UserStoryCustomAttributesValuesViewSet(BaseCustomAttributesValuesViewSet):
|
||||
model = models.UserStoryCustomAttributesValues
|
||||
serializer_class = serializers.UserStoryCustomAttributesValuesSerializer
|
||||
validator_class = validators.UserStoryCustomAttributesValuesValidator
|
||||
permission_classes = (permissions.UserStoryCustomAttributesValuesPermission,)
|
||||
lookup_field = "user_story_id"
|
||||
content_object = "user_story"
|
||||
|
@ -99,6 +104,7 @@ class UserStoryCustomAttributesValuesViewSet(BaseCustomAttributesValuesViewSet):
|
|||
class TaskCustomAttributesValuesViewSet(BaseCustomAttributesValuesViewSet):
|
||||
model = models.TaskCustomAttributesValues
|
||||
serializer_class = serializers.TaskCustomAttributesValuesSerializer
|
||||
validator_class = validators.TaskCustomAttributesValuesValidator
|
||||
permission_classes = (permissions.TaskCustomAttributesValuesPermission,)
|
||||
lookup_field = "task_id"
|
||||
content_object = "task"
|
||||
|
@ -112,6 +118,7 @@ class TaskCustomAttributesValuesViewSet(BaseCustomAttributesValuesViewSet):
|
|||
class IssueCustomAttributesValuesViewSet(BaseCustomAttributesValuesViewSet):
|
||||
model = models.IssueCustomAttributesValues
|
||||
serializer_class = serializers.IssueCustomAttributesValuesSerializer
|
||||
validator_class = validators.IssueCustomAttributesValuesValidator
|
||||
permission_classes = (permissions.IssueCustomAttributesValuesPermission,)
|
||||
lookup_field = "issue_id"
|
||||
content_object = "issue"
|
||||
|
|
|
@ -17,131 +17,51 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from django.apps import apps
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from taiga.base.fields import JsonField
|
||||
from taiga.base.api.serializers import ValidationError
|
||||
from taiga.base.api.serializers import ModelSerializer
|
||||
|
||||
from . import models
|
||||
from taiga.base.fields import JsonField, Field
|
||||
from taiga.base.api import serializers
|
||||
|
||||
|
||||
######################################################
|
||||
# Custom Attribute Serializer
|
||||
#######################################################
|
||||
|
||||
class BaseCustomAttributeSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
read_only_fields = ('id',)
|
||||
exclude = ('created_date', 'modified_date')
|
||||
|
||||
def _validate_integrity_between_project_and_name(self, attrs, source):
|
||||
"""
|
||||
Check the name is not duplicated in the project. Check when:
|
||||
- create a new one
|
||||
- update the name
|
||||
- update the project (move to another project)
|
||||
"""
|
||||
data_id = attrs.get("id", None)
|
||||
data_name = attrs.get("name", None)
|
||||
data_project = attrs.get("project", None)
|
||||
|
||||
if self.object:
|
||||
data_id = data_id or self.object.id
|
||||
data_name = data_name or self.object.name
|
||||
data_project = data_project or self.object.project
|
||||
|
||||
model = self.Meta.model
|
||||
qs = (model.objects.filter(project=data_project, name=data_name)
|
||||
.exclude(id=data_id))
|
||||
if qs.exists():
|
||||
raise ValidationError(_("Already exists one with the same name."))
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_name(self, attrs, source):
|
||||
return self._validate_integrity_between_project_and_name(attrs, source)
|
||||
|
||||
def validate_project(self, attrs, source):
|
||||
return self._validate_integrity_between_project_and_name(attrs, source)
|
||||
class BaseCustomAttributeSerializer(serializers.LightSerializer):
|
||||
name = Field()
|
||||
description = Field()
|
||||
type = Field()
|
||||
order = Field()
|
||||
project = Field(attr="project_id")
|
||||
created_date = Field()
|
||||
modified_date = Field()
|
||||
|
||||
|
||||
class UserStoryCustomAttributeSerializer(BaseCustomAttributeSerializer):
|
||||
class Meta(BaseCustomAttributeSerializer.Meta):
|
||||
model = models.UserStoryCustomAttribute
|
||||
pass
|
||||
|
||||
|
||||
class TaskCustomAttributeSerializer(BaseCustomAttributeSerializer):
|
||||
class Meta(BaseCustomAttributeSerializer.Meta):
|
||||
model = models.TaskCustomAttribute
|
||||
pass
|
||||
|
||||
|
||||
class IssueCustomAttributeSerializer(BaseCustomAttributeSerializer):
|
||||
class Meta(BaseCustomAttributeSerializer.Meta):
|
||||
model = models.IssueCustomAttribute
|
||||
pass
|
||||
|
||||
|
||||
######################################################
|
||||
# Custom Attribute Serializer
|
||||
#######################################################
|
||||
|
||||
|
||||
class BaseCustomAttributesValuesSerializer(ModelSerializer):
|
||||
attributes_values = JsonField(source="attributes_values", label="attributes values")
|
||||
_custom_attribute_model = None
|
||||
_container_field = None
|
||||
|
||||
class Meta:
|
||||
exclude = ("id",)
|
||||
|
||||
def validate_attributes_values(self, attrs, source):
|
||||
# values must be a dict
|
||||
data_values = attrs.get("attributes_values", None)
|
||||
if self.object:
|
||||
data_values = (data_values or self.object.attributes_values)
|
||||
|
||||
if type(data_values) is not dict:
|
||||
raise ValidationError(_("Invalid content. It must be {\"key\": \"value\",...}"))
|
||||
|
||||
# Values keys must be in the container object project
|
||||
data_container = attrs.get(self._container_field, None)
|
||||
if data_container:
|
||||
project_id = data_container.project_id
|
||||
elif self.object:
|
||||
project_id = getattr(self.object, self._container_field).project_id
|
||||
else:
|
||||
project_id = None
|
||||
|
||||
values_ids = list(data_values.keys())
|
||||
qs = self._custom_attribute_model.objects.filter(project=project_id,
|
||||
id__in=values_ids)
|
||||
if qs.count() != len(values_ids):
|
||||
raise ValidationError(_("It contain invalid custom fields."))
|
||||
|
||||
return attrs
|
||||
class BaseCustomAttributesValuesSerializer(serializers.LightSerializer):
|
||||
attributes_values = Field()
|
||||
version = Field()
|
||||
|
||||
|
||||
class UserStoryCustomAttributesValuesSerializer(BaseCustomAttributesValuesSerializer):
|
||||
_custom_attribute_model = models.UserStoryCustomAttribute
|
||||
_container_model = "userstories.UserStory"
|
||||
_container_field = "user_story"
|
||||
|
||||
class Meta(BaseCustomAttributesValuesSerializer.Meta):
|
||||
model = models.UserStoryCustomAttributesValues
|
||||
user_story = Field(attr="user_story.id")
|
||||
|
||||
|
||||
class TaskCustomAttributesValuesSerializer(BaseCustomAttributesValuesSerializer, ModelSerializer):
|
||||
_custom_attribute_model = models.TaskCustomAttribute
|
||||
_container_field = "task"
|
||||
|
||||
class Meta(BaseCustomAttributesValuesSerializer.Meta):
|
||||
model = models.TaskCustomAttributesValues
|
||||
class TaskCustomAttributesValuesSerializer(BaseCustomAttributesValuesSerializer):
|
||||
task = Field(attr="task.id")
|
||||
|
||||
|
||||
class IssueCustomAttributesValuesSerializer(BaseCustomAttributesValuesSerializer, ModelSerializer):
|
||||
_custom_attribute_model = models.IssueCustomAttribute
|
||||
_container_field = "issue"
|
||||
|
||||
class Meta(BaseCustomAttributesValuesSerializer.Meta):
|
||||
model = models.IssueCustomAttributesValues
|
||||
class IssueCustomAttributesValuesSerializer(BaseCustomAttributesValuesSerializer):
|
||||
issue = Field(attr="issue.id")
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
|
||||
# Copyright (C) 2014-2016 Jesús Espino <jespinog@gmail.com>
|
||||
# Copyright (C) 2014-2016 David Barragán <bameda@dbarragan.com>
|
||||
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from taiga.base.fields import JsonField
|
||||
from taiga.base.api.serializers import ValidationError
|
||||
from taiga.base.api.validators import ModelValidator
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
######################################################
|
||||
# Custom Attribute Validator
|
||||
#######################################################
|
||||
|
||||
class BaseCustomAttributeValidator(ModelValidator):
|
||||
class Meta:
|
||||
read_only_fields = ('id',)
|
||||
exclude = ('created_date', 'modified_date')
|
||||
|
||||
def _validate_integrity_between_project_and_name(self, attrs, source):
|
||||
"""
|
||||
Check the name is not duplicated in the project. Check when:
|
||||
- create a new one
|
||||
- update the name
|
||||
- update the project (move to another project)
|
||||
"""
|
||||
data_id = attrs.get("id", None)
|
||||
data_name = attrs.get("name", None)
|
||||
data_project = attrs.get("project", None)
|
||||
|
||||
if self.object:
|
||||
data_id = data_id or self.object.id
|
||||
data_name = data_name or self.object.name
|
||||
data_project = data_project or self.object.project
|
||||
|
||||
model = self.Meta.model
|
||||
qs = (model.objects.filter(project=data_project, name=data_name)
|
||||
.exclude(id=data_id))
|
||||
if qs.exists():
|
||||
raise ValidationError(_("Already exists one with the same name."))
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_name(self, attrs, source):
|
||||
return self._validate_integrity_between_project_and_name(attrs, source)
|
||||
|
||||
def validate_project(self, attrs, source):
|
||||
return self._validate_integrity_between_project_and_name(attrs, source)
|
||||
|
||||
|
||||
class UserStoryCustomAttributeValidator(BaseCustomAttributeValidator):
|
||||
class Meta(BaseCustomAttributeValidator.Meta):
|
||||
model = models.UserStoryCustomAttribute
|
||||
|
||||
|
||||
class TaskCustomAttributeValidator(BaseCustomAttributeValidator):
|
||||
class Meta(BaseCustomAttributeValidator.Meta):
|
||||
model = models.TaskCustomAttribute
|
||||
|
||||
|
||||
class IssueCustomAttributeValidator(BaseCustomAttributeValidator):
|
||||
class Meta(BaseCustomAttributeValidator.Meta):
|
||||
model = models.IssueCustomAttribute
|
||||
|
||||
|
||||
######################################################
|
||||
# Custom Attribute Validator
|
||||
#######################################################
|
||||
|
||||
|
||||
class BaseCustomAttributesValuesValidator(ModelValidator):
|
||||
attributes_values = JsonField(source="attributes_values", label="attributes values")
|
||||
_custom_attribute_model = None
|
||||
_container_field = None
|
||||
|
||||
class Meta:
|
||||
exclude = ("id",)
|
||||
|
||||
def validate_attributes_values(self, attrs, source):
|
||||
# values must be a dict
|
||||
data_values = attrs.get("attributes_values", None)
|
||||
if self.object:
|
||||
data_values = (data_values or self.object.attributes_values)
|
||||
|
||||
if type(data_values) is not dict:
|
||||
raise ValidationError(_("Invalid content. It must be {\"key\": \"value\",...}"))
|
||||
|
||||
# Values keys must be in the container object project
|
||||
data_container = attrs.get(self._container_field, None)
|
||||
if data_container:
|
||||
project_id = data_container.project_id
|
||||
elif self.object:
|
||||
project_id = getattr(self.object, self._container_field).project_id
|
||||
else:
|
||||
project_id = None
|
||||
|
||||
values_ids = list(data_values.keys())
|
||||
qs = self._custom_attribute_model.objects.filter(project=project_id,
|
||||
id__in=values_ids)
|
||||
if qs.count() != len(values_ids):
|
||||
raise ValidationError(_("It contain invalid custom fields."))
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
class UserStoryCustomAttributesValuesValidator(BaseCustomAttributesValuesValidator):
|
||||
_custom_attribute_model = models.UserStoryCustomAttribute
|
||||
_container_model = "userstories.UserStory"
|
||||
_container_field = "user_story"
|
||||
|
||||
class Meta(BaseCustomAttributesValuesValidator.Meta):
|
||||
model = models.UserStoryCustomAttributesValues
|
||||
|
||||
|
||||
class TaskCustomAttributesValuesValidator(BaseCustomAttributesValuesValidator, ModelValidator):
|
||||
_custom_attribute_model = models.TaskCustomAttribute
|
||||
_container_field = "task"
|
||||
|
||||
class Meta(BaseCustomAttributesValuesValidator.Meta):
|
||||
model = models.TaskCustomAttributesValues
|
||||
|
||||
|
||||
class IssueCustomAttributesValuesValidator(BaseCustomAttributesValuesValidator, ModelValidator):
|
||||
_custom_attribute_model = models.IssueCustomAttribute
|
||||
_container_field = "issue"
|
||||
|
||||
class Meta(BaseCustomAttributesValuesValidator.Meta):
|
||||
model = models.IssueCustomAttributesValues
|
Loading…
Reference in New Issue