from django.contrib.admin.options import get_content_type_for_model from django.conf import settings as django_settings from django.utils.encoding import force_text from django.utils.module_loading import autodiscover_modules from django.utils.translation import ugettext as _ from rest_framework.routers import DefaultRouter from orchestra import settings from orchestra.utils.python import import_class from .helpers import insert_links class LogApiMixin(object): def create(self, request, *args, **kwargs): from django.contrib.admin.models import ADDITION response = super(LogApiMixin, self).create(request, *args, **kwargs) message = _('Added.') self.log(request, message, ADDITION, instance=self.serializer.instance) return response def perform_create(self, serializer): """ stores serializer for accessing instance on create() """ super(LogApiMixin, self).perform_create(serializer) self.serializer = serializer def update(self, request, *args, **kwargs): from django.contrib.admin.models import CHANGE response = super(LogApiMixin, self).update(request, *args, **kwargs) message = _('Changed data') self.log(request, message, CHANGE) return response def partial_update(self, request, *args, **kwargs): from django.contrib.admin.models import CHANGE response = super(LogApiMixin, self).partial_update(request, *args, **kwargs) message = _('Changed %s') % str(response.data) self.log(request, message, CHANGE) return response def destroy(self, request, *args, **kwargs): from django.contrib.admin.models import DELETION message = _('Deleted') self.log(request, message, DELETION) response = super(LogApiMixin, self).destroy(request, *args, **kwargs) return response def log(self, request, message, action, instance=None): from django.contrib.admin.models import LogEntry instance = instance or self.get_object() LogEntry.objects.log_action( user_id=request.user.pk, content_type_id=get_content_type_for_model(instance).pk, object_id=instance.pk, object_repr=force_text(instance), action_flag=action, change_message=message, ) class LinkHeaderRouter(DefaultRouter): def get_api_root_view(self): """ returns the root view, with all the linked collections """ APIRoot = import_class(settings.ORCHESTRA_API_ROOT_VIEW) APIRoot.router = self return APIRoot.as_view() def register(self, prefix, viewset, base_name=None): """ inserts link headers on every viewset """ if base_name is None: base_name = self.get_default_base_name(viewset) 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.queryset.model == prefix_or_model: return viewset msg = "%s does not have a regiestered viewset" % prefix_or_model raise KeyError(msg) def insert(self, prefix_or_model, name, field, **kwargs): """ Dynamically add new fields to an existing serializer """ viewset = self.get_viewset(prefix_or_model) if viewset.serializer_class is None: viewset.serializer_class = viewset().get_serializer_class() viewset.serializer_class._declared_fields.update({name: field(**kwargs)}) viewset.serializer_class.Meta.fields += (name,) # Create a router and register our viewsets with it. router = LinkHeaderRouter(trailing_slash=django_settings.APPEND_SLASH) autodiscover = lambda: (autodiscover_modules('api'), autodiscover_modules('serializers'))