diff --git a/orchestra/api/options.py b/orchestra/api/options.py index a27ba72b..a56c3565 100644 --- a/orchestra/api/options.py +++ b/orchestra/api/options.py @@ -90,16 +90,20 @@ class LinkHeaderRouter(DefaultRouter): insert_links(viewset, base_name) self.registry.append((prefix, viewset, base_name)) + def get_viewset(self, prefix_or_model): + for _prefix, viewset, __ in self.registry: + if _prefix == prefix_or_model or viewset.model == prefix_or_model: + return viewset + def insert(self, prefix_or_model, name, field, **kwargs): """ Dynamically add new fields to an existing serializer """ - for _prefix, viewset, basename in self.registry: - if _prefix == prefix_or_model or viewset.model == prefix_or_model: - if viewset.serializer_class is None: - viewset.serializer_class = viewset().get_serializer_class() - viewset.serializer_class.Meta.fields += (name,) - viewset.serializer_class.base_fields.update({name: field(**kwargs)}) - setattr(viewset, 'inserted', getattr(viewset, 'inserted', [])) - viewset.inserted.append(name) + viewset = self.get_viewset(prefix_or_model) + if viewset.serializer_class is None: + viewset.serializer_class = viewset().get_serializer_class() + viewset.serializer_class.Meta.fields += (name,) + viewset.serializer_class.base_fields.update({name: field(**kwargs)}) + setattr(viewset, 'inserted', getattr(viewset, 'inserted', [])) + viewset.inserted.append(name) # Create a router and register our viewsets with it. diff --git a/orchestra/apps/resources/admin.py b/orchestra/apps/resources/admin.py index f714b062..7f6ba1fe 100644 --- a/orchestra/apps/resources/admin.py +++ b/orchestra/apps/resources/admin.py @@ -96,6 +96,7 @@ def resource_inline_factory(resources): verbose_name_plural = _("resources") form = ResourceForm formset = ResourceInlineFormSet + can_delete = False class Media: css = { diff --git a/orchestra/apps/resources/backends.py b/orchestra/apps/resources/backends.py index 0ba02c4f..da9cc8f8 100644 --- a/orchestra/apps/resources/backends.py +++ b/orchestra/apps/resources/backends.py @@ -25,7 +25,7 @@ class ServiceMonitor(ServiceBackend): try: # TODO replace #return MonitorData.objects.filter(content_object=obj).latest().date - ct = ContentType.objects.get(app_label=obj._meta.app_label, model=obj._meta.model_name) + ct = ContentType.objects.get_for_model(type(obj)) return MonitorData.objects.filter(content_type=ct, object_id=obj.pk).latest().date except MonitorData.DoesNotExist: return self.get_current_date() - datetime.timedelta(days=1) diff --git a/orchestra/apps/resources/models.py b/orchestra/apps/resources/models.py index 4cc85c7a..fa34d83d 100644 --- a/orchestra/apps/resources/models.py +++ b/orchestra/apps/resources/models.py @@ -103,7 +103,7 @@ class ResourceData(models.Model): object_id = models.PositiveIntegerField() used = models.PositiveIntegerField(null=True) last_update = models.DateTimeField(null=True) - allocated = models.PositiveIntegerField(null=True) + allocated = models.PositiveIntegerField(null=True, blank=True) content_object = GenericForeignKey() diff --git a/orchestra/apps/resources/serializers.py b/orchestra/apps/resources/serializers.py index 9cb36e8a..f63f5332 100644 --- a/orchestra/apps/resources/serializers.py +++ b/orchestra/apps/resources/serializers.py @@ -7,9 +7,6 @@ from .models import Resource, ResourceData class ResourceSerializer(serializers.ModelSerializer): - # TODO required allocation serializers (like resource form) - # TODO create missing ResourceData (like resource form) - # TODO make default allocation available on OPTIONS (like resource form) name = serializers.SerializerMethodField('get_name') class Meta: @@ -19,9 +16,52 @@ class ResourceSerializer(serializers.ModelSerializer): def get_name(self, instance): return instance.resource.name + + def get_identity(self, data): + return data.get('name') +# Monkey-patching section + if not running_syncdb(): for resources in Resource.group_by_content_type(): model = resources[0].content_type.model_class() - router.insert(model, 'resources', ResourceSerializer, required=False) + router.insert(model, 'resources', ResourceSerializer, required=False, many=True) + + 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) + if not resource.ondemand and not data.allocated: + data.allocated = resource.default_allocation + result.append(data) + for resource in resources: + data = ResourceData(resource=resource) + if not resource.ondemand: + 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 + + old_metadata = viewset.metadata + def metadata(self, request, resources=resources): + """ Display resource configuration """ + ret = old_metadata(self, request) + ret['resources'] = [ + { + 'name': resource.name, + 'ondemand': resource.ondemand, + 'default_allocation': resource.default_allocation + } for resource in resources + ] + return ret + viewset.metadata = metadata diff --git a/orchestra/apps/users/roles/mail/backends.py b/orchestra/apps/users/roles/mail/backends.py index a892703c..08e32ada 100644 --- a/orchestra/apps/users/roles/mail/backends.py +++ b/orchestra/apps/users/roles/mail/backends.py @@ -137,7 +137,7 @@ class PostfixAddressBackend(ServiceController): class AutoresponseBackend(ServiceController): verbose_name = _("Mail autoresponse") model = 'mail.Autoresponse' - + class MailDisk(ServiceMonitor): model = 'email.Mailbox'