Skip to content
Snippets Groups Projects
admin.py 4.69 KiB
Newer Older
from abc import ABC, abstractmethod

from django.contrib import admin, messages
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView

from AKModel.forms import AdminIntermediateForm, AdminIntermediateActionForm
from AKModel.models import Event


class EventSlugMixin:
    """
    Mixin to handle views with event slugs
    """
    event = None

    def _load_event(self):
        # Find event based on event slug
        if self.event is None:
            self.event = get_object_or_404(Event, slug=self.kwargs.get("event_slug", None))

    def get(self, request, *args, **kwargs):
        self._load_event()
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self._load_event()
        return super().post(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        self._load_event()
        return super().list(request, *args, **kwargs)

    def create(self, request, *args, **kwargs):
        self._load_event()
        return super().create(request, *args, **kwargs)

    def dispatch(self, request, *args, **kwargs):
        if self.event is None:
            self._load_event()
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(object_list=object_list, **kwargs)
        # Add event to context (to make it accessible in templates)
        context["event"] = self.event
        return context


class FilterByEventSlugMixin(EventSlugMixin):
    """
    Mixin to filter different querysets based on a event slug from the request url
    """

    def get_queryset(self):
        # Filter current queryset based on url event slug or return 404 if event slug is invalid
        return super().get_queryset().filter(event=self.event)


class AdminViewMixin:
    site_url = ''
    title = ''

    def get_context_data(self, **kwargs):
        extra = admin.site.each_context(self.request)
        extra.update(super().get_context_data(**kwargs))

        if self.site_url != '':
            extra["site_url"] = self.site_url
        if self.title != '':
            extra["title"] = self.title

        return extra


class IntermediateAdminView(AdminViewMixin, FormView):
    template_name = "admin/AKModel/action_intermediate.html"
    form_class = AdminIntermediateForm

    def get_preview(self):
        return ""

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["title"] = self.title
        context["preview"] = self.get_preview()
        return context


class WizardViewMixin:
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["wizard_step"] = self.wizard_step
        context["wizard_steps"] = [
            _("Start"),
            _("Settings"),
            _("Event created, Prepare Import"),
            _("Import categories & requirements"),
            _("Activate?"),
            _("Finish")
        ]
        context["wizard_step_text"] = context["wizard_steps"][self.wizard_step - 1]
        context["wizard_steps_total"] = len(context["wizard_steps"])
        return context


class IntermediateAdminActionView(IntermediateAdminView, ABC):
    form_class = AdminIntermediateActionForm
    entities = None

    def get_queryset(self, pks=None):
        if pks is None:
            pks = self.request.GET['pks']
        return self.model.objects.filter(pk__in=pks.split(","))

    def get_initial(self):
        initial = super().get_initial()
        initial['pks'] = self.request.GET['pks']
        return initial

    def get_preview(self):
        self.entities = self.get_queryset()
        joined_entities = '\n'.join(str(e) for e in self.entities)
        return f"{self.confirmation_message}:\n\n {joined_entities}"

    def get_success_url(self):
        return reverse(f"admin:{self.model._meta.app_label}_{self.model._meta.model_name}_changelist")

    @abstractmethod
    def action(self, form):
        pass

    def form_valid(self, form):
        self.entities = self.get_queryset(pks=form.cleaned_data['pks'])
        self.action(form)
        messages.add_message(self.request, messages.SUCCESS, self.success_message)
        return super().form_valid(form)


class LoopActionMixin(ABC):
    def action(self, form):
        self.pre_action()
        for entity in self.entities:
            self.perform_action(entity)
            entity.save()
        self.post_action()

    @abstractmethod
    def perform_action(self, entity):
        pass

    def pre_action(self):
        pass

    def post_action(self):
        pass