django-orchestra/orchestra/apps/resources/admin.py

203 lines
7.9 KiB
Python
Raw Normal View History

2014-07-10 15:19:06 +00:00
from django.contrib import admin, messages
2014-07-08 15:19:15 +00:00
from django.contrib.contenttypes import generic
2014-10-27 13:29:02 +00:00
from django.core.urlresolvers import reverse
2014-07-08 15:19:15 +00:00
from django.utils.functional import cached_property
2014-10-23 15:38:46 +00:00
from django.utils.safestring import mark_safe
2014-10-27 13:29:02 +00:00
from django.utils.translation import ugettext, ugettext_lazy as _
2014-07-08 15:19:15 +00:00
2014-07-10 15:19:06 +00:00
from orchestra.admin import ExtendedModelAdmin
2014-07-08 15:19:15 +00:00
from orchestra.admin.filters import UsedContentTypeFilter
2014-07-22 21:47:01 +00:00
from orchestra.admin.utils import insertattr, get_modeladmin, admin_link, admin_date
2014-07-10 10:03:22 +00:00
from orchestra.core import services
2014-10-09 17:04:12 +00:00
from orchestra.utils import database_ready
2014-07-08 15:19:15 +00:00
2014-10-27 13:29:02 +00:00
from .actions import run_monitor
2014-07-08 15:19:15 +00:00
from .forms import ResourceForm
2014-07-09 16:17:43 +00:00
from .models import Resource, ResourceData, MonitorData
2014-07-08 15:19:15 +00:00
2014-07-10 15:19:06 +00:00
class ResourceAdmin(ExtendedModelAdmin):
2014-07-08 15:19:15 +00:00
list_display = (
2014-09-26 15:05:20 +00:00
'id', 'verbose_name', 'content_type', 'period', 'on_demand',
2014-10-24 14:19:34 +00:00
'default_allocation', 'unit', 'crontab', 'is_active'
2014-07-08 15:19:15 +00:00
)
2014-10-24 14:19:34 +00:00
list_display_links = ('id', 'verbose_name')
list_editable = ('default_allocation', 'crontab', 'is_active',)
2014-09-26 15:05:20 +00:00
list_filter = (UsedContentTypeFilter, 'period', 'on_demand', 'disable_trigger')
2014-07-10 15:19:06 +00:00
fieldsets = (
(None, {
2014-10-23 15:38:46 +00:00
'fields': ('verbose_name', 'name', 'content_type', 'period'),
2014-07-10 15:19:06 +00:00
}),
(_("Configuration"), {
2014-10-23 15:38:46 +00:00
'fields': ('unit', 'scale', 'on_demand', 'default_allocation', 'disable_trigger',
'is_active'),
2014-07-10 15:19:06 +00:00
}),
(_("Monitoring"), {
'fields': ('monitors', 'crontab'),
}),
)
change_readonly_fields = ('name', 'content_type', 'period')
2014-10-24 14:19:34 +00:00
prepopulated_fields = {'name': ('verbose_name',)}
2014-07-10 15:19:06 +00:00
def add_view(self, request, **kwargs):
""" Warning user if the node is not fully configured """
2014-07-17 16:09:24 +00:00
if request.method == 'POST':
2014-10-23 15:38:46 +00:00
messages.warning(request, mark_safe(_(
"Restarting orchestra and celerybeat is required to fully apply changes.<br> "
2014-07-17 16:09:24 +00:00
"Remember that new allocated values will be applied when objects are saved."
2014-10-23 15:38:46 +00:00
)))
2014-07-10 15:19:06 +00:00
return super(ResourceAdmin, self).add_view(request, **kwargs)
2014-07-10 10:03:22 +00:00
2014-07-08 15:19:15 +00:00
def save_model(self, request, obj, form, change):
super(ResourceAdmin, self).save_model(request, obj, form, change)
model = obj.content_type.model_class()
2014-07-18 15:32:27 +00:00
modeladmin = type(get_modeladmin(model))
2014-07-08 15:19:15 +00:00
resources = obj.content_type.resource_set.filter(is_active=True)
inlines = []
for inline in modeladmin.inlines:
2014-07-09 16:17:43 +00:00
if inline.model is ResourceData:
2014-07-08 15:19:15 +00:00
inline = resource_inline_factory(resources)
inlines.append(inline)
modeladmin.inlines = inlines
2014-07-10 10:03:22 +00:00
def formfield_for_dbfield(self, db_field, **kwargs):
""" filter service content_types """
if db_field.name == 'content_type':
2014-07-21 12:20:04 +00:00
models = [ model._meta.model_name for model in services.get() ]
2014-07-10 10:03:22 +00:00
kwargs['queryset'] = db_field.rel.to.objects.filter(model__in=models)
return super(ResourceAdmin, self).formfield_for_dbfield(db_field, **kwargs)
2014-07-08 15:19:15 +00:00
2014-10-27 13:29:02 +00:00
class ResourceDataAdmin(ExtendedModelAdmin):
2014-07-16 15:20:16 +00:00
list_display = (
2014-10-27 13:29:02 +00:00
'id', 'resource_link', 'content_object_link', 'used', 'allocated', 'display_unit',
'display_updated'
2014-07-16 15:20:16 +00:00
)
2014-07-08 15:19:15 +00:00
list_filter = ('resource',)
2014-10-27 13:29:02 +00:00
add_fields = ('resource', 'content_type', 'object_id', 'used', 'updated_at', 'allocated')
fields = (
'resource_link', 'content_type', 'content_object_link', 'used', 'display_updated',
'allocated', 'display_unit'
)
readonly_fields = ('display_unit',)
change_readonly_fields = (
'resource_link', 'content_type', 'content_object_link', 'used', 'display_updated',
'display_unit'
)
actions = (run_monitor,)
change_view_actions = actions
ordering = ('-updated_at',)
2014-11-02 14:33:55 +00:00
prefetch_related = ('content_object',)
2014-09-28 12:28:57 +00:00
resource_link = admin_link('resource')
2014-07-21 15:43:36 +00:00
content_object_link = admin_link('content_object')
2014-10-27 13:29:02 +00:00
display_updated = admin_date('updated_at', short_description=_("Updated"))
def display_unit(self, data):
return data.unit
display_unit.short_description = _("Unit")
display_unit.admin_order_field = 'resource__unit'
2014-07-08 15:19:15 +00:00
2014-10-27 13:29:02 +00:00
class MonitorDataAdmin(ExtendedModelAdmin):
list_display = ('id', 'monitor', 'display_created', 'value', 'content_object_link')
2014-07-08 15:19:15 +00:00
list_filter = ('monitor',)
2014-10-27 13:29:02 +00:00
add_fields = ('monitor', 'content_type', 'object_id', 'created_at', 'value')
fields = ('monitor', 'content_type', 'content_object_link', 'display_created', 'value')
change_readonly_fields = fields
2014-07-11 21:09:17 +00:00
2014-07-21 15:43:36 +00:00
content_object_link = admin_link('content_object')
2014-10-27 13:29:02 +00:00
display_created = admin_date('created_at', short_description=_("Created"))
2014-09-10 16:53:09 +00:00
def get_queryset(self, request):
queryset = super(MonitorDataAdmin, self).get_queryset(request)
return queryset.prefetch_related('content_object')
2014-07-08 15:19:15 +00:00
admin.site.register(Resource, ResourceAdmin)
2014-07-09 16:17:43 +00:00
admin.site.register(ResourceData, ResourceDataAdmin)
2014-07-08 15:19:15 +00:00
admin.site.register(MonitorData, MonitorDataAdmin)
# Mokey-patching
def resource_inline_factory(resources):
class ResourceInlineFormSet(generic.BaseGenericInlineFormSet):
2014-07-22 21:47:01 +00:00
def total_form_count(self, resources=resources):
2014-07-08 15:19:15 +00:00
return len(resources)
@cached_property
2014-07-22 21:47:01 +00:00
def forms(self, resources=resources):
2014-07-08 15:19:15 +00:00
forms = []
2014-07-22 21:47:01 +00:00
resources_copy = list(resources)
2014-10-27 13:29:02 +00:00
queryset = self.queryset
if self.instance.pk:
# Create missing resource data
queryset = list(queryset)
queryset_resources = [data.resource for data in queryset]
for resource in resources:
if resource not in queryset_resources:
data = resource.dataset.create(content_object=self.instance)
queryset.append(data)
# Existing dataset
for i, data in enumerate(queryset):
2014-07-22 21:47:01 +00:00
forms.append(self._construct_form(i, resource=data.resource))
resources_copy.remove(data.resource)
2014-10-27 13:29:02 +00:00
# Missing dataset
for i, resource in enumerate(resources_copy, len(queryset)):
2014-07-08 15:19:15 +00:00
forms.append(self._construct_form(i, resource=resource))
return forms
class ResourceInline(generic.GenericTabularInline):
2014-07-09 16:17:43 +00:00
model = ResourceData
2014-07-08 15:19:15 +00:00
verbose_name_plural = _("resources")
form = ResourceForm
formset = ResourceInlineFormSet
2014-07-10 17:34:23 +00:00
can_delete = False
2014-07-16 15:20:16 +00:00
fields = (
2014-10-27 13:29:02 +00:00
'verbose_name', 'display_used', 'display_updated', 'allocated', 'unit',
2014-07-16 15:20:16 +00:00
)
2014-10-27 13:29:02 +00:00
readonly_fields = ('display_used', 'display_updated')
2014-07-08 15:19:15 +00:00
class Media:
css = {
'all': ('orchestra/css/hide-inline-id.css',)
}
2014-09-26 15:05:20 +00:00
display_updated = admin_date('updated_at', default=_("Never"))
2014-07-22 21:47:01 +00:00
2014-10-27 13:29:02 +00:00
def display_used(self, data):
update_link = ''
if data.pk:
url = reverse('admin:resources_resourcedata_monitor', args=(data.pk,))
update_link = '<a href="%s"><strong>%s</strong></a>' % (url, ugettext("Update"))
if data.used is not None:
return '%s %s %s' % (data.used, data.resource.unit, update_link)
return _("Unknonw %s") % update_link
display_used.short_description = _("Used")
2014-07-08 15:19:15 +00:00
def has_add_permission(self, *args, **kwargs):
""" Hidde add another """
return False
2014-10-27 13:29:02 +00:00
2014-07-08 15:19:15 +00:00
return ResourceInline
2014-10-04 14:19:29 +00:00
def insert_resource_inlines():
2014-10-07 13:08:59 +00:00
# Clean previous state
for related in Resource._related:
modeladmin = get_modeladmin(related)
modeladmin_class = type(modeladmin)
for inline in getattr(modeladmin_class, 'inlines', []):
if inline.__name__ == 'ResourceInline':
modeladmin_class.inlines.remove(inline)
for ct, resources in Resource.objects.group_by('content_type').iteritems():
2014-07-08 15:19:15 +00:00
inline = resource_inline_factory(resources)
2014-07-25 13:27:31 +00:00
model = ct.model_class()
2014-10-07 13:08:59 +00:00
insertattr(model, 'inlines', inline)
2014-10-09 17:04:12 +00:00
2014-10-07 13:08:59 +00:00
if database_ready():
insert_resource_inlines()