django-orchestra/orchestra/contrib/websites/serializers.py

103 lines
3.8 KiB
Python

from django.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404
from rest_framework import serializers
from orchestra.api.serializers import HyperlinkedModelSerializer
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
from .models import Website, Content, WebsiteDirective
from .validators import validate_domain_protocol
class RelatedDomainSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSerializer):
class Meta:
model = Website.domains.field.rel.to
fields = ('url', 'id', 'name')
def from_native(self, data, files=None):
queryset = self.opts.model.objects.filter(account=self.account)
return get_object_or_404(queryset, name=data['name'])
class RelatedWebAppSerializer(AccountSerializerMixin, serializers.HyperlinkedModelSerializer):
class Meta:
model = Content.webapp.field.rel.to
fields = ('url', 'id', 'name', 'type')
def from_native(self, data, files=None):
queryset = self.opts.model.objects.filter(account=self.account)
return get_object_or_404(queryset, name=data['name'])
class ContentSerializer(serializers.HyperlinkedModelSerializer):
webapp = RelatedWebAppSerializer()
class Meta:
model = Content
fields = ('webapp', 'path')
def get_identity(self, data):
return '%s-%s' % (data.get('website'), data.get('path'))
class DirectiveSerializer(serializers.ModelSerializer):
class Meta:
model = WebsiteDirective
fields = ('name', 'value')
def to_representation(self, instance):
return {prop.name: prop.value for prop in instance.all()}
def to_internal_value(self, data):
return data
class WebsiteSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
domains = RelatedDomainSerializer(many=True, required=False) #allow_add_remove=True
contents = ContentSerializer(required=False, many=True, #allow_add_remove=True,
source='content_set')
directives = DirectiveSerializer(required=False)
class Meta:
model = Website
fields = ('url', 'id', 'name', 'protocol', 'domains', 'is_active', 'contents', 'directives')
postonly_fileds = ('name',)
def full_clean(self, instance):
""" Prevent multiples domains on the same protocol """
for domain in instance._m2m_data['domains']:
try:
validate_domain_protocol(instance, domain, instance.protocol)
except ValidationError as e:
# TODO not sure about this one
self.add_error(None, e)
return instance
def create(self, validated_data):
directives_data = validated_data.pop('directives')
webapp = super(WebsiteSerializer, self).create(validated_data)
for key, value in directives_data.items():
WebsiteDirective.objects.create(webapp=webapp, name=key, value=value)
return webap
def update(self, instance, validated_data):
directives_data = validated_data.pop('directives')
instance = super(WebsiteSerializer, self).update(instance, validated_data)
existing = {}
for obj in instance.directives.all():
existing[obj.name] = obj
posted = set()
for key, value in directives_data.items():
posted.add(key)
try:
directive = existing[key]
except KeyError:
directive = instance.directives.create(name=key, value=value)
else:
if directive.value != value:
directive.value = value
directive.save(update_fields=('value',))
for to_delete in set(existing.keys())-posted:
existing[to_delete].delete()
return instance