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

91 lines
3.3 KiB
Python
Raw Normal View History

2014-07-08 16:37:38 +00:00
from rest_framework import serializers
from orchestra.api import router
from orchestra.utils.db import database_ready
2014-07-08 16:37:38 +00:00
2014-07-09 16:17:43 +00:00
from .models import Resource, ResourceData
2014-07-08 16:37:38 +00:00
class ResourceSerializer(serializers.ModelSerializer):
2015-04-23 14:34:04 +00:00
name = serializers.SerializerMethodField()
unit = serializers.ReadOnlyField()
2014-07-08 16:37:38 +00:00
class Meta:
2014-07-09 16:17:43 +00:00
model = ResourceData
2014-10-27 14:31:04 +00:00
fields = ('name', 'used', 'allocated', 'unit')
2014-07-09 16:17:43 +00:00
read_only_fields = ('used',)
2014-07-08 16:37:38 +00:00
2014-10-06 14:57:02 +00:00
def from_native(self, raw_data, files=None):
data = super(ResourceSerializer, self).from_native(raw_data, files=files)
if not data.resource_id:
data.resource = Resource.objects.get(name=raw_data['name'])
return data
2014-07-08 16:37:38 +00:00
def get_name(self, instance):
return instance.resource.name
2014-07-10 17:34:23 +00:00
def get_identity(self, data):
return data.get('name')
2014-07-08 16:37:38 +00:00
2014-07-10 17:34:23 +00:00
# Monkey-patching section
2014-07-08 16:37:38 +00:00
2014-10-06 14:57:02 +00:00
def insert_resource_serializers():
2014-10-07 13:08:59 +00:00
# clean previous state
for related in Resource._related:
viewset = router.get_viewset(related)
fields = list(viewset.serializer_class.Meta.fields)
try:
fields.remove('resources')
except ValueError:
pass
viewset.serializer_class.Meta.fields = fields
# Create nested serializers on target models
2015-04-02 16:14:55 +00:00
for ct, resources in Resource.objects.group_by('content_type').items():
2014-07-25 15:17:50 +00:00
model = ct.model_class()
2014-07-21 15:43:36 +00:00
try:
router.insert(model, 'resources', ResourceSerializer, required=False, many=True, source='resource_set')
2014-07-21 15:43:36 +00:00
except KeyError:
continue
2014-10-06 14:57:02 +00:00
# TODO this is a fucking workaround, reimplement this on the proper place
2014-07-10 17:34:23 +00:00
def validate_resources(self, attrs, source, _resources=resources):
""" Creates missing resources """
posted = attrs.get(source, [])
result = []
resources = list(_resources)
for data in posted:
resource = data.resource
if resource not in resources:
msg = "Unknown or duplicated resource '%s'." % resource
raise serializers.ValidationError(msg)
resources.remove(resource)
2014-09-26 15:05:20 +00:00
if not resource.on_demand and not data.allocated:
2014-07-10 17:34:23 +00:00
data.allocated = resource.default_allocation
result.append(data)
for resource in resources:
data = ResourceData(resource=resource)
2014-09-26 15:05:20 +00:00
if not resource.on_demand:
2014-07-10 17:34:23 +00:00
data.allocated = resource.default_allocation
result.append(data)
attrs[source] = result
return attrs
viewset = router.get_viewset(model)
viewset.serializer_class.validate_resources = validate_resources
2015-04-23 14:34:04 +00:00
old_options = viewset.options
def options(self, request, resources=resources):
2014-07-11 14:48:46 +00:00
""" Provides available resources description """
2015-04-23 14:34:04 +00:00
metadata = old_options(self, request)
metadata.data['available_resources'] = [
2014-07-10 17:34:23 +00:00
{
'name': resource.name,
2014-09-26 15:05:20 +00:00
'on_demand': resource.on_demand,
2014-07-10 17:34:23 +00:00
'default_allocation': resource.default_allocation
} for resource in resources
]
2015-04-23 14:34:04 +00:00
return metadata
viewset.options = options
2014-10-06 14:57:02 +00:00
if database_ready():
insert_resource_serializers()