Source code for shuup.xtheme.plugins.forms
# -*- coding: utf-8 -*-
# This file is part of Shuup.
#
# Copyright (c) 2012-2021, Shuup Commerce Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
import six
from collections import OrderedDict
from copy import deepcopy
from django import forms
from django.conf import settings
from shuup.xtheme.plugins.consts import FALLBACK_LANGUAGE_CODE
[docs]class PluginForm(forms.Form):
"""
Base class for plugin configuration forms.
"""
def __init__(self, **kwargs):
self.plugin = kwargs.pop("plugin")
self.request = kwargs.pop("request")
super(PluginForm, self).__init__(**kwargs)
self.populate()
self.set_defaults()
self.init_translated_fields()
[docs] def populate(self): # pragma: no cover, doccov: ignore
# Subclass hook (overriding __init__ all the time is such a bore)
pass
[docs] def init_translated_fields(self):
self.translatable_field_names = []
self.monolingual_field_names = []
languages = self.get_languages()
new_fields = OrderedDict()
for name, field in six.iteritems(self.fields):
if isinstance(field, TranslatableField):
self.translatable_field_names.append(name)
for language_code in languages:
key = "%s_%s" % (name, language_code)
new_fields[key] = deepcopy(field)
new_fields[key].initial = self.plugin.get_translated_value(name, language=language_code)
new_fields[key].required = False
elif field:
self.monolingual_field_names.append(name)
new_fields[name] = field
self.fields = new_fields
[docs] def set_defaults(self):
"""
Set the forms initial values based on plugin defaults
Use the plugin's default configuration as the default form field
initial values.
"""
for key, value in self.plugin.get_defaults().items():
if key in self.fields and self.fields[key].initial is None:
self.fields[key].initial = value
[docs] def full_clean(self):
"""
Use initial values as defaults for cleaned data
"""
super(PluginForm, self).full_clean()
for name in self.fields:
if name in self.cleaned_data:
continue
if self.fields[name].initial is not None:
self.cleaned_data[name] = self.fields[name].initial
self.cleaned_data
[docs] def get_config(self):
"""
Get the new `config` dict for a plugin.
Called when the form is valid, akin to
`django.forms.models.ModelForm.save`.
The default implementation just augments the old config with the
cleaned data for the form.
:return: A new JSONable (!) config dict
:rtype: dict
"""
config = self.plugin.config.copy()
data = self.cleaned_data.copy()
languages = self.get_languages()
for field_name in self.translatable_field_names:
data[field_name] = {}
for language_code in languages:
key = "%s_%s" % (field_name, language_code)
val = self.cleaned_data.get(key, "")
if val not in ["", None]:
data[field_name][language_code] = val
del data[key]
config.update(data)
return config
[docs] def get_languages(self):
default_language = settings.PARLER_DEFAULT_LANGUAGE_CODE
languages = [language[0] for language in settings.LANGUAGES]
if default_language in languages:
languages.remove(default_language)
return [default_language] + languages + [FALLBACK_LANGUAGE_CODE]
[docs]class GenericPluginForm(PluginForm):
"""
A generic form for Xtheme plugins; populates itself based on `fields` in the plugin class.
"""
[docs] def populate(self): # doccov: ignore
fields = self.plugin.fields
if hasattr(fields, "items"): # Quacks like a dict; that's fine too
fields = fields.items()
for name, field in fields:
self.fields[name] = deepcopy(field)
self.initial.update(self.plugin.config)