mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-21 02:41:53 +00:00
326 lines
11 KiB
Python
326 lines
11 KiB
Python
import copy
|
|
import logging
|
|
|
|
from ....base import (
|
|
clean_dict,
|
|
get_ignorable_form_fields,
|
|
get_ordered_form_handler_plugins,
|
|
integration_form_callback_registry,
|
|
integration_form_element_plugin_registry,
|
|
IntegrationFormElementPluginProcessor,
|
|
)
|
|
from ....helpers import get_ignorable_form_values
|
|
|
|
from . import UID
|
|
from .helpers import map_field_name_to_label
|
|
|
|
__title__ = 'fobi.contrib.apps.drf_integration.base'
|
|
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
|
__copyright__ = '2016-2018 Artur Barseghyan'
|
|
__license__ = 'GPL 2.0/LGPL 2.1'
|
|
__all__ = (
|
|
'DRFIntegrationFormElementPluginProcessor',
|
|
'DRFSubmitPluginFormDataMixin',
|
|
'get_cleaned_data',
|
|
'get_field_name_to_label_map',
|
|
'get_processed_serializer_data',
|
|
'run_form_handlers',
|
|
'submit_plugin_form_data',
|
|
)
|
|
|
|
|
|
DEBUG = True
|
|
LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
class DRFIntegrationFormElementPluginProcessor(
|
|
IntegrationFormElementPluginProcessor
|
|
):
|
|
"""Django REST framework field instance processor."""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(DRFIntegrationFormElementPluginProcessor, self).__init__(
|
|
*args,
|
|
**kwargs
|
|
)
|
|
self.field_class = kwargs.get('field_class')
|
|
self.field_kwargs = kwargs.get('field_kwargs', {})
|
|
self.field_metadata = kwargs.get('field_metadata', {})
|
|
self.form_element_plugin = kwargs.get('form_element_plugin')
|
|
self.data = self.form_element_plugin.data \
|
|
if self.form_element_plugin \
|
|
else {}
|
|
|
|
def process_custom_form_field_instance(self,
|
|
form_element_entry,
|
|
form_entry,
|
|
request,
|
|
form_element_plugin=None):
|
|
"""Process."""
|
|
if form_element_plugin:
|
|
self.form_element_plugin = form_element_plugin
|
|
self.data = form_element_plugin.data
|
|
|
|
return self
|
|
|
|
|
|
class DRFSubmitPluginFormDataMixin(object):
|
|
"""Submit plugin form data mixin."""
|
|
|
|
def _submit_plugin_form_data(self,
|
|
form_element_plugin,
|
|
form_entry,
|
|
request,
|
|
serializer,
|
|
form_element_entries=None,
|
|
**kwargs):
|
|
"""Submit plugin form data (internal method).
|
|
|
|
Do not override this method. Use ``submit_plugin_form_data``,
|
|
instead.
|
|
|
|
Submit plugin form data. Called on form submission (when user actually
|
|
posts the data to assembled form).
|
|
|
|
:param form_element_plugin:
|
|
:param fobi.models.FormEntry form_entry: Instance of
|
|
``fobi.models.FormEntry``.
|
|
:param django.http.HttpRequest request:
|
|
:param rest_framework.serializers.Serializer serializer:
|
|
:param iterable form_element_entries:
|
|
"""
|
|
if DEBUG:
|
|
return self.submit_plugin_form_data(
|
|
form_element_plugin=form_element_plugin,
|
|
form_entry=form_entry,
|
|
request=request,
|
|
serializer=serializer,
|
|
form_element_entries=form_element_entries,
|
|
**kwargs
|
|
)
|
|
else:
|
|
try:
|
|
return self.submit_plugin_form_data(
|
|
form_element_plugin=form_element_plugin,
|
|
form_entry=form_entry,
|
|
request=request,
|
|
serializer=serializer,
|
|
form_element_entries=form_element_entries,
|
|
**kwargs
|
|
)
|
|
except Exception as err:
|
|
LOGGER.debug(str(err))
|
|
|
|
def submit_plugin_form_data(self,
|
|
form_element_plugin,
|
|
form_entry,
|
|
request,
|
|
serializer,
|
|
form_element_entries=None,
|
|
**kwargs):
|
|
"""Submit plugin form data.
|
|
|
|
Called on form submission (when user actually
|
|
posts the data to assembled form).
|
|
|
|
:param form_element_plugin:
|
|
:param fobi.models.FormEntry form_entry: Instance of
|
|
``fobi.models.FormEntry``.
|
|
:param django.http.HttpRequest request:
|
|
:param rest_framework.serializers.Serializer serializer:
|
|
:param iterable form_element_entries:
|
|
"""
|
|
|
|
|
|
def fire_form_callbacks(form_entry, request, serializer, stage=None):
|
|
"""Fire DRF integration form callbacks.
|
|
|
|
:param fobi.models.FormEntry form_entry:
|
|
:param django.http.HttpRequest request:
|
|
:param rest_framework.serializers.Serializer serializer:
|
|
:param string stage:
|
|
:return rest_framework.serializers.Serializer serializer:
|
|
"""
|
|
callbacks = integration_form_callback_registry.get_callbacks(
|
|
integrate_with=UID,
|
|
stage=stage
|
|
)
|
|
for callback_cls in callbacks:
|
|
callback = callback_cls()
|
|
updated_serializer = callback.callback(
|
|
form_entry=form_entry,
|
|
request=request,
|
|
serializer=serializer
|
|
)
|
|
if updated_serializer:
|
|
serializer = updated_serializer
|
|
return serializer
|
|
|
|
|
|
def run_form_handlers(form_entry,
|
|
request,
|
|
serializer,
|
|
form_element_entries=None):
|
|
"""Run form handlers.
|
|
|
|
:param fobi.models.FormEntry form_entry:
|
|
:param django.http.HttpRequest request:
|
|
:param rest_framework.serializers.Serializer serializer:
|
|
:param iterable form_element_entries:
|
|
:return tuple: List of success responses, list of error responses
|
|
"""
|
|
# Errors list
|
|
errors = []
|
|
|
|
# Responses of successfully processed handlers
|
|
responses = []
|
|
|
|
# Getting form handler plugins in their execution order.
|
|
ordered_form_handlers = get_ordered_form_handler_plugins()
|
|
|
|
# Getting the form handlers to be executed.
|
|
form_handlers = form_entry.formhandlerentry_set.order_by('plugin_uid')[:]
|
|
|
|
# Assembling a new dictionary of the form handlers to iterate later.
|
|
for form_handler in form_handlers:
|
|
ordered_form_handlers[form_handler.plugin_uid].append(form_handler)
|
|
|
|
# Iterating through the form handlers in the order
|
|
# specified in the settings.
|
|
for uid, form_handlers in ordered_form_handlers.items():
|
|
# logger.debug("UID: {0}".format(uid))
|
|
for form_handler in form_handlers:
|
|
# Get the form handler plugin
|
|
form_handler_plugin = form_handler.get_plugin(request=request)
|
|
|
|
# Run the form handler
|
|
success, response = \
|
|
form_handler_plugin._run_integration_handler(
|
|
integrate_with=UID,
|
|
form_entry=form_entry,
|
|
request=request,
|
|
serializer=serializer,
|
|
form_element_entries=form_element_entries,
|
|
)
|
|
|
|
if success:
|
|
responses.append((form_handler_plugin, response))
|
|
else:
|
|
errors.append((form_handler_plugin, response))
|
|
|
|
return responses, errors
|
|
|
|
|
|
def submit_plugin_form_data(form_entry,
|
|
request,
|
|
serializer,
|
|
form_element_entries=None,
|
|
**kwargs):
|
|
"""Submit plugin form data for all plugins.
|
|
|
|
:param fobi.models.FormEntry form_entry: Instance of
|
|
``fobi.models.FormEntry``.
|
|
:param django.http.HttpRequest request:
|
|
:param rest_framework.serializers.Serializer serializer:
|
|
:param iterable form_element_entries:
|
|
"""
|
|
if not form_element_entries:
|
|
form_element_entries = form_entry.formelemententry_set.all()
|
|
for form_element_entry in form_element_entries:
|
|
# Get the plugin.
|
|
form_element_plugin = form_element_entry.get_plugin(request=request)
|
|
custom_plugin_cls = integration_form_element_plugin_registry.get(
|
|
integrate_with=UID,
|
|
uid=form_element_plugin.uid
|
|
)
|
|
if custom_plugin_cls:
|
|
custom_plugin = custom_plugin_cls()
|
|
updated_serializer = \
|
|
custom_plugin._submit_plugin_form_data(
|
|
form_element_plugin=form_element_plugin,
|
|
form_entry=form_entry,
|
|
request=request,
|
|
serializer=serializer,
|
|
form_element_entries=form_element_entries,
|
|
**kwargs
|
|
)
|
|
if updated_serializer:
|
|
serializer = updated_serializer
|
|
|
|
return serializer
|
|
|
|
|
|
def get_processed_serializer_data(serializer, form_element_entries):
|
|
"""Gets processed serializer data.
|
|
|
|
Simply fires both ``fobi.base.get_cleaned_data`` and
|
|
``fobi.base.get_field_name_to_label_map`` functions and returns the
|
|
result.
|
|
|
|
:param serializer:
|
|
:param iterable form_element_entries: Iterable of form element entries.
|
|
:return tuple:
|
|
"""
|
|
keys_to_remove = get_ignorable_form_fields(form_element_entries)
|
|
values_to_remove = get_ignorable_form_values()
|
|
|
|
field_name_to_label_map = \
|
|
get_field_name_to_label_map(serializer,
|
|
keys_to_remove,
|
|
values_to_remove)
|
|
|
|
keys_to_remove = list(field_name_to_label_map.keys())
|
|
|
|
return (
|
|
field_name_to_label_map,
|
|
get_cleaned_data(serializer, keys_to_remove, values_to_remove)
|
|
)
|
|
|
|
|
|
def get_field_name_to_label_map(serializer,
|
|
keys_to_remove=[],
|
|
values_to_remove=[]):
|
|
"""Get field name to label map.
|
|
|
|
:param serializer:
|
|
:param iterable keys_to_remove:
|
|
:param iterable values_to_remove:
|
|
:return dict:
|
|
"""
|
|
if not keys_to_remove:
|
|
keys_to_remove = get_ignorable_form_fields([])
|
|
|
|
if not values_to_remove:
|
|
values_to_remove = get_ignorable_form_values()
|
|
|
|
field_name_to_label_map = clean_dict(
|
|
map_field_name_to_label(serializer),
|
|
keys_to_remove,
|
|
values_to_remove
|
|
)
|
|
|
|
return field_name_to_label_map
|
|
|
|
|
|
def get_cleaned_data(serializer, keys_to_remove=[], values_to_remove=[]):
|
|
"""Get cleaned data.
|
|
|
|
Gets cleaned data, having the trash (fields without values) filtered
|
|
out.
|
|
|
|
:param serializer:
|
|
:param iterable keys_to_remove:
|
|
:param iterable values_to_remove:
|
|
:return dict:
|
|
"""
|
|
if not values_to_remove:
|
|
values_to_remove = get_ignorable_form_values()
|
|
|
|
cleaned_data = copy.copy(serializer.validated_data)
|
|
cleaned_data = clean_dict(
|
|
cleaned_data,
|
|
keys=list(set(cleaned_data.keys()) - set(keys_to_remove)),
|
|
values=values_to_remove
|
|
)
|
|
|
|
return cleaned_data
|