Source code for shuup.admin.form_part
# -*- 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.
from django.core.exceptions import ValidationError
from django.db.transaction import atomic
from django.http import HttpResponseRedirect
from shuup.admin.signals import object_created, object_saved, view_form_valid
from shuup.admin.utils.urls import get_model_url
from shuup.admin.utils.views import add_create_or_change_message
from shuup.apps.provides import get_provide_objects
from shuup.utils.form_group import FormDef, FormGroup
[docs]class TemplatedFormDef(FormDef):
def __init__(self, name, form_class, template_name, required=True, kwargs=None):
self.template_name = template_name
super(TemplatedFormDef, self).__init__(name=name, form_class=form_class, required=required, kwargs=kwargs)
[docs]class FormPart(object):
priority = 0
def __init__(self, request, object=None):
self.request = request
self.object = object
[docs]class FormPartsViewMixin(object):
fields = () # Dealt with by the FormGroup
request = None
form_part_class_provide_key = None
base_form_part_classes = ()
[docs] def get_form_class(self):
return None # Dealt with by `get_form`; this will just squelch Django warnings
[docs] def get_form_part_classes(self):
form_part_classes = list(self.base_form_part_classes) + list(
get_provide_objects(self.form_part_class_provide_key)
)
return form_part_classes
[docs] def get_form_parts(self, object):
form_part_classes = self.get_form_part_classes()
form_parts = [form_part_class(request=self.request, object=object) for form_part_class in form_part_classes]
form_parts.sort(key=lambda form_part: getattr(form_part, "priority", 0))
return form_parts
[docs] def get_form(self, form_class=None):
kwargs = self.get_form_kwargs()
instance = kwargs.pop("instance", None)
if not instance.pk:
kwargs["initial"] = dict(self.request.GET.items())
fg = FormGroup(**kwargs)
form_parts = self.get_form_parts(instance)
for form_part in form_parts:
for form_def in form_part.get_form_defs():
fg.form_defs[form_def.name] = form_def
fg.instantiate_forms()
return fg
[docs]class SaveFormPartsMixin(object):
request = None # Placate "missing field" errors
object = None # --"--
@atomic()
[docs] def save_form_parts(self, form):
# trigger signal for extra form validations
try:
view_form_valid.send(sender=type(self), view=self, form=form, request=self.request)
except ValidationError:
return self.form_invalid(form)
is_new = not self.object.pk
form_parts = self.get_form_parts(self.object)
for form_part in form_parts:
retval = form_part.form_valid(form)
if retval is not None: # Allow a form part to change the identity of the object
self.object = retval
for form_part in form_parts:
form_part.object = self.object
if is_new:
object_created.send(sender=type(self.object), object=self.object, request=self.request)
object_saved.send(sender=type(self.object), object=self.object, request=self.request)
self._add_create_or_change_message(self.request, self.object, is_new)
if self.request.GET.get("redirect") and not self.request.POST.get("__next"):
return HttpResponseRedirect(self.request.GET.get("redirect"))
if hasattr(self, "get_success_url"):
return HttpResponseRedirect(self.get_success_url())
if is_new:
return HttpResponseRedirect(get_model_url(self.object, shop=self.request.shop))
else:
return HttpResponseRedirect(self.request.path)
def _add_create_or_change_message(self, request, object, is_new):
add_create_or_change_message(request, object, is_new)