Source code for fobi.contrib.apps.drf_integration.base
import copy
import logging
from ....base import (
IntegrationFormElementPluginProcessor,
clean_dict,
get_ignorable_form_fields,
get_ordered_form_handler_plugins,
integration_form_callback_registry,
integration_form_element_plugin_registry,
)
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-2019 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__)
[docs]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 {}
)
[docs] 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
[docs]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))
[docs] 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
[docs]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
[docs]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
[docs]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),
)
[docs]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
[docs]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