from django.contrib import admin, messages
from django.contrib.admin import helpers
from django.contrib.admin.views.decorators import staff_member_required
from django.shortcuts import redirect, render
from django.urls import re_path as url
from django.utils.decorators import method_decorator
from django.utils.html import strip_tags
from django.utils.translation import gettext_lazy as _
from .constants import ACTION_CHOICE_REPLACE
from .forms import (
BulkChangeFormElementPluginsForm,
BulkChangeFormHandlerPluginsForm,
BulkChangeFormWizardHandlerPluginsForm,
FormElementEntryForm,
FormHandlerEntryForm,
FormWizardHandlerEntryForm,
)
from .models import (
FormElement,
FormElementEntry,
FormEntry,
FormHandler,
FormHandlerEntry,
FormWizardEntry,
FormWizardFormEntry,
FormWizardHandler,
FormWizardHandlerEntry,
)
__title__ = "fobi.admin"
__author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
__copyright__ = "2014-2019 Artur Barseghyan"
__license__ = "GPL 2.0/LGPL 2.1"
__all__ = (
"base_bulk_change_plugins",
"BasePluginModelAdmin",
"bulk_change_form_element_plugins",
"bulk_change_form_handler_plugins",
"bulk_change_form_wizard_handler_plugins",
"FormElementAdmin",
"FormElementEntryAdmin",
"FormElementEntryInlineAdmin",
"FormEntryAdmin",
"FormFieldsetEntryAdmin",
"FormHandlerAdmin",
"FormHandlerEntryAdmin",
"FormHandlerEntryInlineAdmin",
"FormWizardEntryAdmin",
"FormWizardFormEntryInlineAdmin",
"FormWizardHandlerAdmin",
"FormWizardHandlerEntryInlineAdmin",
)
staff_member_required_m = method_decorator(staff_member_required)
# *****************************************************************************
# *****************************************************************************
# ******************************* Admin helpers *******************************
# *****************************************************************************
# *****************************************************************************
[docs]def base_bulk_change_plugins(
PluginForm, named_url, modeladmin, request, queryset
):
"""Bulk change of plugins action additional view."""
opts = modeladmin.model._meta
app_label = opts.app_label
selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)
post = dict(request.POST)
if selected:
post["selected_plugins"] = ",".join(selected)
if request.method == "POST":
form = PluginForm(
data=post,
files=request.FILES,
initial={"selected_plugins": ",".join(selected)},
)
else:
form = PluginForm(initial={"selected_plugins": ",".join(selected)})
context = {
"form": form,
"app_label": app_label,
"opts": opts,
"action_checkbox_name": helpers.ACTION_CHECKBOX_NAME,
"named_url": named_url,
}
template_name = "fobi/admin/bulk_change_plugins.html"
return render(request, template_name, context)
# *****************************************************************************
# *****************************************************************************
# ******************************* Entry admin *********************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# ******************************* Form entry admin ****************************
# *****************************************************************************
[docs]class FormElementEntryInlineAdmin(admin.TabularInline):
"""FormElementEntry inline admin."""
model = FormElementEntry
form = FormElementEntryForm
fields = (
"form_entry",
"plugin_uid",
"plugin_data",
"position",
)
extra = 0
[docs]class FormHandlerEntryInlineAdmin(admin.TabularInline):
"""FormHandlerEntry inline admin."""
model = FormHandlerEntry
form = FormHandlerEntryForm
fields = (
"form_entry",
"plugin_uid",
"plugin_data",
)
extra = 0
[docs]class FormEntryAdmin(admin.ModelAdmin):
"""FormEntry admin."""
list_display = (
"name",
"slug",
"user",
"is_public",
"is_active",
"created",
"updated",
"is_cloneable",
)
list_editable = ("is_public", "is_cloneable")
list_filter = ("is_public", "is_cloneable")
readonly_fields = ("slug",)
radio_fields = {"user": admin.VERTICAL}
fieldsets = (
(
_("Form"),
{
"fields": (
"name",
"is_public",
"is_cloneable",
"active_date_from",
"active_date_to",
"inactive_page_title",
"inactive_page_message",
)
},
),
(
_("Custom"),
{
"classes": ("collapse",),
"fields": (
"success_page_title",
"success_page_message",
"action",
),
},
),
# (_("Wizard"), {
# 'classes': ('collapse',),
# 'fields': ('form_wizard_entry', 'position',)
# }),
(_("User"), {"classes": ("collapse",), "fields": ("user",)}),
(_("Additional"), {"classes": ("collapse",), "fields": ("slug",)}),
)
inlines = [FormElementEntryInlineAdmin, FormHandlerEntryInlineAdmin]
[docs] class Meta(object):
"""Meta."""
app_label = _("Fobi")
admin.site.register(FormEntry, FormEntryAdmin)
# *****************************************************************************
# *************************** Form wizard entry admin *************************
# *****************************************************************************
[docs]class FormWizardFormEntryInlineAdmin(admin.TabularInline):
"""FormWizardFormEntry inline admin."""
model = FormWizardFormEntry
# form = FormElementEntryForm
fields = (
"form_entry",
"position",
)
extra = 0
[docs]class FormWizardHandlerEntryInlineAdmin(admin.TabularInline):
"""FormWizardHandlerEntry inline admin."""
model = FormWizardHandlerEntry
form = FormWizardHandlerEntryForm
fields = (
"plugin_uid",
"plugin_data",
)
extra = 0
[docs]class FormWizardEntryAdmin(admin.ModelAdmin):
"""FormWizardEntry admin."""
list_display = (
"name",
"slug",
"user",
"is_public",
"created",
"updated",
"is_cloneable",
)
list_editable = (
"is_public",
"is_cloneable",
)
list_filter = (
"is_public",
"is_cloneable",
)
readonly_fields = ("slug",)
radio_fields = {"user": admin.VERTICAL}
fieldsets = (
(
_("Form"),
{
"fields": (
"name",
"is_public",
"is_cloneable",
)
},
),
(
_("Custom"),
{
"classes": ("collapse",),
"fields": (
"success_page_title",
"success_page_message",
),
},
),
# (_("Wizard"), {
# 'classes': ('collapse',),
# 'fields': ('form_wizard_entry', 'position',)
# }),
(_("User"), {"classes": ("collapse",), "fields": ("user",)}),
(_("Additional"), {"classes": ("collapse",), "fields": ("slug",)}),
)
inlines = [
FormWizardFormEntryInlineAdmin,
FormWizardHandlerEntryInlineAdmin,
]
[docs] class Meta(object):
"""Meta."""
app_label = _("Fobi")
admin.site.register(FormWizardEntry, FormWizardEntryAdmin)
# *****************************************************************************
# ************************* Form fieldset entry admin *************************
# *****************************************************************************
[docs]class FormFieldsetEntryAdmin(admin.ModelAdmin):
"""FormEieldsetEntry admin."""
list_display = ("form_entry", "name", "is_repeatable")
list_editable = ("is_repeatable",)
list_filter = ("is_repeatable",)
# readonly_fields = ('slug',)
fieldsets = ((None, {"fields": ("form_entry", "name", "is_repeatable")}),)
[docs] class Meta(object):
"""Meta."""
app_label = _("Fobi")
# admin.site.register(FormFieldsetEntry, FormFieldsetEntryAdmin)
# *****************************************************************************
# ************************** Form element entry admin *************************
# *****************************************************************************
[docs]class FormElementEntryAdmin(admin.ModelAdmin):
"""FormElementEntry admin."""
list_display = (
"plugin_uid",
"plugin_uid_code",
"plugin_data",
"position",
"form_entry",
)
list_filter = ("form_entry", "plugin_uid")
list_editable = ("position",)
readonly_fields = ("plugin_uid_code",)
fieldsets = (
(
_("Plugin"),
{
"fields": (
"plugin_uid",
"plugin_data",
)
},
),
(
_("Form"),
{
"fields": (
"form_entry",
"form_fieldset_entry",
"position",
)
},
),
)
[docs] class Meta(object):
"""Meta."""
app_label = _("Fobi")
[docs] def get_queryset(self, request):
"""Get queryset."""
qs = super(FormElementEntryAdmin, self).get_queryset(request)
qs = qs.select_related("form_entry", "form_fieldset_entry")
return qs
# admin.site.register(FormElementEntry, FormElementEntryAdmin)
# *****************************************************************************
# ************************** Form element entry admin *************************
# *****************************************************************************
[docs]class FormHandlerEntryAdmin(admin.ModelAdmin):
"""FormHandlerEntry admin."""
list_display = (
"plugin_uid",
"plugin_uid_code",
"plugin_data",
"form_entry",
)
list_filter = ("form_entry", "plugin_uid")
readonly_fields = ("plugin_uid_code",)
fieldsets = (
(
_("Plugin"),
{
"fields": (
"plugin_uid",
"plugin_data",
)
},
),
(_("Form"), {"fields": ("form_entry",)}),
)
[docs] class Meta(object):
"""Meta."""
app_label = _("Form handler entry")
[docs] def get_queryset(self, request):
"""Tweak the queryset."""
qs = super(FormHandlerEntryAdmin, self).get_queryset(request)
qs = qs.select_related(
"form_entry",
)
return qs
# admin.site.register(FormHandlerEntry, FormHandlerEntryAdmin)
# *****************************************************************************
# *****************************************************************************
# ******************************* Plugin admin ********************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# ********************************** Abstract *********************************
# *****************************************************************************
[docs]class BasePluginModelAdmin(admin.ModelAdmin):
"""Base plugin admin."""
list_display = ("plugin_uid_admin", "users_list", "groups_list")
readonly_fields = ("plugin_uid", "plugin_uid_admin")
fieldsets = ((None, {"fields": ("plugin_uid", "users", "groups")}),)
filter_horizontal = (
"users",
"groups",
)
[docs] def has_add_permission(self, request):
"""Has add permissions.
We don't want to allow to add form elements/handlers manually. It
should happen using the management command ``fobi_sync_plugins``
instead.
"""
return False
[docs] def get_queryset(self, request):
"""Tweak queryset."""
qs = super(BasePluginModelAdmin, self).get_queryset(request)
qs = qs.prefetch_related("users", "groups")
return qs
def _get_bulk_change_form_class(self):
"""Get change form class for bulk actions."""
raise NotImplementedError(
"You should implement `get_bulk_change_form_class`"
)
def _get_model(self):
"""Get model."""
raise NotImplementedError("You should implement `_get_model`")
def _get_changelist_named_url(self):
"""Get changelist named URL."""
raise NotImplementedError(
"You should implement `_get_changelist_named_url`"
)
[docs] @staff_member_required_m
def bulk_change_plugins(self, request):
"""Bulk change plugins.
This is where the data is actually processed.
"""
changelist_named_url = self._get_changelist_named_url()
if request.method == "POST":
form_cls = self._get_bulk_change_form_class()
form = form_cls(data=request.POST, files=request.FILES)
if form.is_valid():
ids = form.cleaned_data.pop("selected_plugins").split(",")
users = form.cleaned_data.pop("users")
groups = form.cleaned_data.pop("groups")
users_action = form.cleaned_data.pop("users_action")
groups_action = form.cleaned_data.pop("groups_action")
cleaned_data = dict(
(key, val)
for (key, val) in form.cleaned_data.items()
if val is not None
)
# Queryset to work with
PluginModel = self._get_model()
queryset = PluginModel._default_manager.filter(pk__in=ids)
# Update simple fields
updated = queryset.update(**cleaned_data)
# Update groups
for plugin_model_entry in queryset:
# If groups action chose is ``replace``, clearing
# the groups first.
if groups_action == ACTION_CHOICE_REPLACE:
plugin_model_entry.groups.clear()
# If users action chose is ``replace``, clearing
# the users first.
if users_action == ACTION_CHOICE_REPLACE:
plugin_model_entry.users.clear()
plugin_model_entry.groups.add(*groups) # Adding groups
plugin_model_entry.users.add(*users) # Adding users
messages.info(
request,
_("{0} plugins were changed " "successfully.").format(
len(ids)
),
)
return redirect(changelist_named_url)
else:
messages.warning(
request,
_("Form contains " "errors: {}").format(
strip_tags(form.errors)
),
)
return redirect(changelist_named_url)
else:
messages.warning(request, _("POST required when changing in bulk!"))
return redirect(changelist_named_url)
# *****************************************************************************
# ********************************** Form element *****************************
# *****************************************************************************
admin.site.register(FormElement, FormElementAdmin)
# *****************************************************************************
# *********************************** Form handler ****************************
# *****************************************************************************
admin.site.register(FormHandler, FormHandlerAdmin)
# *****************************************************************************
# ****************************** Form wizard handler **************************
# *****************************************************************************
admin.site.register(FormWizardHandler, FormWizardHandlerAdmin)