mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-10 22:03:09 +00:00
Merge branch 'master' into wagtail/integration
This commit is contained in:
commit
7700a5f28e
45 changed files with 930 additions and 135 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -36,7 +36,6 @@ README_PARTS.rst
|
|||
|
||||
/src/django_fobi.egg-info
|
||||
/src/fobi/contrib/plugins/form_elements/fields/hidden_model_object/
|
||||
/src/fobi/contrib/apps/drf_integration/form_elements/content/
|
||||
/src/fobi/contrib/plugins/form_importers/mailchimp_importer/bucket.py
|
||||
/src/fobi/contrib/apps/wagtail_integration_/
|
||||
|
||||
|
|
@ -52,6 +51,7 @@ README_PARTS.rst
|
|||
/examples/media/cache/
|
||||
/examples/simple/lund_urls.py
|
||||
/examples/simple/lund/
|
||||
/examples/saved_forms_in_json_format/all/
|
||||
/examples/simple/settings/local_settings.py
|
||||
/examples/simple/settings/local_settings_foundation5.py
|
||||
/examples/simple/settings/bootstrap3_theme_django_1_9_lund.py
|
||||
|
|
|
|||
|
|
@ -15,8 +15,30 @@ are used for versioning (schema follows below):
|
|||
0.3.4 to 0.4).
|
||||
- All backwards incompatible changes are mentioned in this document.
|
||||
|
||||
0.11
|
||||
----
|
||||
0.11.4
|
||||
------
|
||||
2017-05-12
|
||||
|
||||
- Minor fixes in integration callbacks of the ``drf_integration`` sub-package.
|
||||
- Added support for ``content_image``, ``content_text`` and ``content_video``
|
||||
plugins.
|
||||
- Fixes in installable demo.
|
||||
|
||||
0.11.3
|
||||
------
|
||||
2017-05-10
|
||||
|
||||
- Concept of integration callbacks introduced and implemented for the
|
||||
``drf_integration`` sub-package.
|
||||
|
||||
0.11.2
|
||||
------
|
||||
2017-05-09
|
||||
|
||||
- Minor fixes in ``drf_integration`` app.
|
||||
|
||||
0.11.1
|
||||
------
|
||||
2017-05-08
|
||||
|
||||
- Minor fixes in ``decimal`` plugin.
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ mkdir ../static/
|
|||
mkdir ../db/
|
||||
mkdir ../logs/
|
||||
mkdir ../tmp/
|
||||
cp local_settings.example local_settings.py
|
||||
./manage.py syncdb --noinput --traceback -v 3
|
||||
cp settings/local_settings.example settings/local_settings.py
|
||||
#./manage.py syncdb --noinput --traceback -v 3
|
||||
./manage.py migrate --noinput
|
||||
./manage.py collectstatic --noinput --traceback -v 3
|
||||
./manage.py fobi_create_test_data --traceback -v 3
|
||||
./manage.py runserver 0.0.0.0:8001 --traceback -v 3
|
||||
./manage.py runserver 0.0.0.0:8001 --traceback -v 3
|
||||
|
|
|
|||
|
|
@ -1,13 +1 @@
|
|||
-r common.txt
|
||||
-r djangorestframework.txt
|
||||
|
||||
Django>=1.8,<1.9
|
||||
django-admin-tools>=0.7.1
|
||||
django-autoslug==1.9.3
|
||||
django-debug-toolbar==0.11
|
||||
django-formtools==1.0
|
||||
django-nine>=0.1.10
|
||||
django-nonefield>=0.1
|
||||
django-registration-redux>=1.4
|
||||
easy-thumbnails>=2.3
|
||||
vishap>=0.1.5
|
||||
-r django_1_9.txt
|
||||
|
|
|
|||
4
examples/saved_forms_in_json_format/README.rst
Normal file
4
examples/saved_forms_in_json_format/README.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Saved forms in JSON format
|
||||
==========================
|
||||
A nice collection of saved ``django-fobi`` forms. Importable using the
|
||||
import functionality.
|
||||
1
examples/saved_forms_in_json_format/change-payment-method.json
Executable file
1
examples/saved_forms_in_json_format/change-payment-method.json
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"success_page_message": "", "is_public": false, "success_page_title": "", "slug": "change-payment-method", "form_handlers": [], "action": "", "name": "Change Payment Method", "is_cloneable": false, "form_elements": [{"plugin_data": "{\"required\": false, \"name\": \"customer_id\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Customer ID\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 1}, {"plugin_data": "{\"required\": false, \"name\": \"account_hold_name\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Hold Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 2}, {"plugin_data": "{\"required\": false, \"name\": \"account_password\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Password\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 3}, {"plugin_data": "{\"required\": false, \"name\": \"contact_phone_number\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Contact Phone Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 4}, {"plugin_data": "{\"required\": false, \"name\": \"contact_email_address\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Contact email address\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 5}, {"plugin_data": "{\"required\": false, \"name\": \"new_payment_method\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"New Payment Method\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 6}, {"plugin_data": "{\"required\": false, \"name\": \"card_holder_or_account_holder\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Card Holder or Account Holder\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 7}, {"plugin_data": "{\"required\": false, \"name\": \"account_number\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 8}, {"plugin_data": "{\"required\": false, \"name\": \"routing_code_if_electronic_check\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Routing Code (if electronic check)\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 9}, {"plugin_data": "{\"required\": false, \"name\": \"expiration_date_if_card\", \"help_text\": \"\", \"label\": \"Expiration date if Card\", \"input_formats\": \"\", \"initial\": null}", "plugin_uid": "date", "position": 10}, {"plugin_data": "{\"required\": false, \"name\": \"cvv_if_card\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"CVV if Card\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 11}]}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"success_page_message": "", "is_public": false, "success_page_title": "", "slug": "change-responsible-party-on-account", "form_handlers": [], "action": "", "name": "Change Responsible Party on Account", "is_cloneable": false, "form_elements": [{"plugin_data": "{\"required\": true, \"name\": \"customer_id\", \"help_text\": \"\", \"max_length\": 8, \"label\": \"Customer ID\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 1}, {"plugin_data": "{\"required\": true, \"name\": \"name\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Account Hold Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 2}, {"plugin_data": "{\"required\": false, \"name\": \"new_user_first_name\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"New User First Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 3}, {"plugin_data": "{\"required\": false, \"name\": \"new_user_last_name\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"New User Last Name\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 4}, {"plugin_data": "{\"required\": false, \"name\": \"relationship_to_account_holder_if_any\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Relationship to Account Holder, if Any\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 5}, {"plugin_data": "{\"required\": false, \"name\": \"account_password\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Account Password\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 6}, {"plugin_data": "{\"required\": false, \"name\": \"contact_phone_number\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Contact Phone Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 7}, {"plugin_data": "{\"required\": false, \"name\": \"contact_email_address\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Contact email address\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 8}, {"plugin_data": "{\"required\": false, \"choices\": \"1, Electronic Check\\r\\n2, Visa \\r\\n3, Mastercard \\r\\n4, American Express, \\r\\n5, Discover\", \"name\": \"new_payment_method\", \"help_text\": \"\", \"label\": \"New Payment Method\", \"initial\": \"\"}", "plugin_uid": "select", "position": 9}, {"plugin_data": "{\"required\": false, \"name\": \"account_number\", \"help_text\": \"\", \"max_length\": 255, \"label\": \"Account Number\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 10}, {"plugin_data": "{\"required\": false, \"name\": \"routing_code_if_electronic_check\", \"help_text\": \"\", \"max_length\": 50, \"label\": \"Routing Code (if electronic check)\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 11}, {"plugin_data": "{\"required\": false, \"name\": \"expiration_date_if_card\", \"help_text\": \"\", \"label\": \"Expiration date if Card\", \"input_formats\": \"\", \"initial\": null}", "plugin_uid": "date", "position": 12}, {"plugin_data": "{\"required\": false, \"name\": \"cvv_if_card\", \"help_text\": \"\", \"max_length\": 8, \"label\": \"CVV if Card\", \"placeholder\": \"\", \"initial\": \"\"}", "plugin_uid": "text", "position": 13}]}
|
||||
1
examples/saved_forms_in_json_format/otevreny-form.json
Executable file
1
examples/saved_forms_in_json_format/otevreny-form.json
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"name": "Otevreny form (imported on 2016-11-30 21:33:48)", "is_public": false, "form_handlers": [], "form_elements": [{"position": 1, "plugin_uid": "text", "plugin_data": "{\"name\": \"jmeno\", \"max_length\": 80, \"required\": true, \"label\": \"Jm\\u00e9no\", \"help_text\": \"Zadejte sv\\u00e9 jm\\u00e9no\", \"initial\": \"\", \"placeholder\": \"Jm\\u00e9no\"}"}, {"position": 2, "plugin_uid": "text", "plugin_data": "{\"name\": \"prijmeni\", \"max_length\": 255, \"required\": true, \"label\": \"P\\u0159\\u00edjmen\\u00ed\", \"help_text\": \"Zadejte sv\\u00e9 p\\u0159\\u00edjmen\\u00ed\", \"initial\": \"\", \"placeholder\": \"P\\u0159\\u00edjmen\\u00ed\"}"}, {"position": 3, "plugin_uid": "text", "plugin_data": "{\"name\": \"prezdivka\", \"max_length\": 255, \"required\": false, \"label\": \"P\\u0159ezd\\u00edvka\", \"help_text\": \"Zadejte svoji p\\u0159ezd\\u00edvku\", \"initial\": \"\", \"placeholder\": \"P\\u0159ezd\\u00edvka\"}"}, {"position": 4, "plugin_uid": "email", "plugin_data": "{\"name\": \"e_mail\", \"max_length\": 255, \"required\": true, \"label\": \"E-mail\", \"help_text\": \"Zadejte sv\\u016fj e-mail\", \"initial\": \"\", \"placeholder\": \"E-mail\"}"}, {"position": 5, "plugin_uid": "date_drop_down", "plugin_data": "{\"input_formats\": \"\", \"name\": \"datum_narozeni\", \"year_max\": 2050, \"label\": \"Datum narozen\\u00ed\", \"year_min\": 1950, \"help_text\": \"Zadejte sv\\u00e9 datum narozen\\u00ed.\", \"initial\": \"2000\", \"required\": true}"}, {"position": 6, "plugin_uid": "textarea", "plugin_data": "{\"name\": \"dalsi_informace_o_soutezicim\", \"required\": true, \"label\": \"Dal\\u0161\\u00ed informace o sout\\u011b\\u017e\\u00edc\\u00edm\", \"help_text\": \"Z\\u00e1jmy a tak\", \"initial\": \"\", \"placeholder\": \"\"}"}], "slug": "otevreny-form", "success_page_title": "Success page title", "success_page_message": "Success page body", "is_cloneable": false, "action": ""}
|
||||
1
examples/saved_forms_in_json_format/ssi-knee-hip.json
Executable file
1
examples/saved_forms_in_json_format/ssi-knee-hip.json
Executable file
File diff suppressed because one or more lines are too long
1
examples/saved_forms_in_json_format/test-dynamic-values.json
Executable file
1
examples/saved_forms_in_json_format/test-dynamic-values.json
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"form_handlers": [{"plugin_data": null, "plugin_uid": "db_store"}], "name": "Test dynamic values", "action": "", "success_page_message": "", "slug": "test-dynamic-values", "success_page_title": "", "form_elements": [{"plugin_data": "{\"name\": \"username\", \"required\": false, \"help_text\": \"\", \"placeholder\": \"\", \"initial\": \"{{ request.user.get_username }}\", \"max_length\": 255, \"label\": \"Username\"}", "plugin_uid": "text", "position": 136}, {"plugin_data": "{\"name\": \"origin\", \"required\": false, \"help_text\": \"\", \"placeholder\": \"\", \"initial\": \"{{ request.path }}\", \"max_length\": 255, \"label\": \"Origin\"}", "plugin_uid": "text", "position": 137}, {"plugin_data": "{\"name\": \"meta\", \"required\": false, \"help_text\": \"\", \"placeholder\": \"\", \"initial\": \"{{ request.META }}\", \"label\": \"Meta\"}", "plugin_uid": "textarea", "position": 138}, {"plugin_data": "{\"placeholder\": \"\", \"name\": \"test_if_it_breaks\", \"label\": \"Test if it breaks\", \"required\": false, \"help_text\": \"\", \"initial\": \"{% load admin_list %}{% admin_actions %}\\r\\n{{ request.user.get_username }}\\r\\n{{ request.user.email }}\\r\\n{{ request.path }}\\r\\n{{ request.META }}\\r\\n\"}", "plugin_uid": "textarea", "position": 161}], "is_public": false, "is_cloneable": false, "position": null}
|
||||
1
examples/saved_forms_in_json_format/test-form-wizard.json
Executable file
1
examples/saved_forms_in_json_format/test-form-wizard.json
Executable file
File diff suppressed because one or more lines are too long
1
examples/saved_forms_in_json_format/test-private-form.json
Executable file
1
examples/saved_forms_in_json_format/test-private-form.json
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"form_handlers": [{"plugin_data": null, "plugin_uid": "db_store"}], "name": "Test private form", "action": "", "success_page_message": "", "slug": "test-private-form", "success_page_title": "", "form_elements": [{"plugin_data": "{\"required\": true, \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"label\": \"E-mail\", \"name\": \"e_mail\"}", "plugin_uid": "email", "position": 165}, {"plugin_data": "{\"required\": true, \"placeholder\": \"\", \"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"label\": \"Full name\", \"name\": \"full_name\"}", "plugin_uid": "text", "position": 166}, {"plugin_data": "{\"required\": true, \"placeholder\": \"\", \"help_text\": \"\", \"initial\": \"\", \"label\": \"Question\", \"name\": \"question\"}", "plugin_uid": "textarea", "position": 167}, {"plugin_data": "{\"readonly_value\": false, \"name\": \"nombre\", \"help_text\": \"\", \"required\": true, \"min_value\": \"\", \"multiple_value\": false, \"initial\": \"\", \"type_value\": \"text\", \"list_value\": \"5\", \"disabled_value\": false, \"step_value\": null, \"autofocus_value\": true, \"placeholder\": \"nombre\", \"pattern_value\": \"\", \"autocomplete_value\": true, \"label\": \"nombre\", \"max_length\": 255, \"max_value\": \"6\"}", "plugin_uid": "input", "position": 168}, {"plugin_data": "{\"name\": \"apellido\", \"required\": true, \"help_text\": \"\", \"placeholder\": \"apellido\", \"initial\": \"\", \"max_length\": 255, \"label\": \"apellido\"}", "plugin_uid": "text", "position": 169}], "is_public": false, "is_cloneable": false, "position": null}
|
||||
1
examples/saved_forms_in_json_format/test-sliders.json
Executable file
1
examples/saved_forms_in_json_format/test-sliders.json
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"name": "Test sliders", "is_cloneable": false, "form_wizard_forms": [{"action": "", "name": "Test slider form", "is_cloneable": false, "form_elements": [{"plugin_uid": "slider", "position": 1, "plugin_data": "{\"step\": 10, \"initial\": 50, \"tooltip\": \"show\", \"label\": \"Slider variant 1\", \"name\": \"slider_variant_1\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"0, Start\\r\\n50, Middle\\r\\n100, End\", \"min_value\": 0, \"show_endpoints_as\": \"labeled_ticks\", \"label_end\": \"\", \"label_start\": \"\", \"required\": false, \"handle\": \"square\"}"}, {"plugin_uid": "slider", "position": 2, "plugin_data": "{\"step\": 20, \"initial\": 40, \"tooltip\": \"show\", \"label\": \"Slider variant 2\", \"name\": \"slider_variant_2\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"0\\r\\n20\\r\\n40\\r\\n60\\r\\n80\\r\\n100\", \"min_value\": 0, \"show_endpoints_as\": \"labeled_ticks\", \"label_end\": \"\", \"label_start\": \"\", \"required\": false, \"handle\": \"round\"}"}, {"plugin_uid": "slider", "position": 3, "plugin_data": "{\"step\": 25, \"initial\": 50, \"tooltip\": \"show\", \"label\": \"Slider variant 3\", \"name\": \"slider_variant_3\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"\", \"min_value\": 0, \"show_endpoints_as\": \"labels\", \"label_end\": \"100%\", \"label_start\": \"0%\", \"required\": false, \"handle\": \"triangle\"}"}, {"plugin_uid": "slider", "position": 4, "plugin_data": "{\"step\": 10, \"initial\": 50, \"tooltip\": \"hide\", \"label\": \"Slider variant 4\", \"name\": \"slider_variant_4\", \"max_value\": 100, \"help_text\": \"\", \"custom_ticks\": \"\", \"min_value\": 0, \"show_endpoints_as\": \"labels\", \"label_end\": \"\", \"label_start\": \"\", \"required\": false, \"handle\": \"round\"}"}], "success_page_title": "", "slug": "test-slider-form", "form_handlers": [], "success_page_message": "", "is_public": false}, {"action": "", "name": "Flight form", "is_cloneable": false, "form_elements": [{"plugin_uid": "radio", "position": 1, "plugin_data": "{\"help_text\": \"\", \"required\": true, \"initial\": \"\", \"label\": \"Arrival/Departure\", \"name\": \"arrival_departure\", \"choices\": \"A, Arrival\\r\\nD, Departure\\r\\nO, Overfly\"}"}, {"plugin_uid": "text", "position": 2, "plugin_data": "{\"help_text\": \"\", \"max_length\": 50, \"initial\": \"\", \"label\": \"Callsign\", \"name\": \"callsign\", \"placeholder\": \"\", \"required\": true}"}, {"plugin_uid": "text", "position": 3, "plugin_data": "{\"help_text\": \"\", \"max_length\": 255, \"initial\": \"\", \"label\": \"Airport\", \"name\": \"airport\", \"placeholder\": \"Origin/Destination\", \"required\": true}"}, {"plugin_uid": "datetime", "position": 4, "plugin_data": "{\"help_text\": \"\", \"required\": true, \"initial\": null, \"label\": \"Schedule\", \"name\": \"time\", \"input_formats\": \"\"}"}], "success_page_title": "OK", "slug": "flight-form", "form_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "Flight updated", "is_public": false}], "success_page_title": "", "slug": "test-sliders", "form_wizard_handlers": [{"plugin_uid": "db_store", "plugin_data": null}], "success_page_message": "", "is_public": false}
|
||||
1
examples/saved_forms_in_json_format/testing-interesting-project.json
Executable file
1
examples/saved_forms_in_json_format/testing-interesting-project.json
Executable file
File diff suppressed because one or more lines are too long
|
|
@ -2,15 +2,23 @@ from __future__ import print_function
|
|||
|
||||
import logging
|
||||
|
||||
from fobi.base import FormCallback, form_callback_registry
|
||||
from fobi.base import (
|
||||
form_callback_registry,
|
||||
FormCallback,
|
||||
integration_form_callback_registry,
|
||||
IntegrationFormCallback,
|
||||
)
|
||||
|
||||
from fobi.constants import (
|
||||
CALLBACK_BEFORE_FORM_VALIDATION,
|
||||
CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA,
|
||||
CALLBACK_FORM_INVALID,
|
||||
CALLBACK_FORM_VALID,
|
||||
CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS,
|
||||
CALLBACK_FORM_INVALID
|
||||
CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA,
|
||||
)
|
||||
|
||||
from fobi.contrib.apps.drf_integration import UID as INTEGRATE_WITH
|
||||
|
||||
logger = logging.getLogger('fobi')
|
||||
|
||||
__all__ = (
|
||||
|
|
@ -18,6 +26,12 @@ __all__ = (
|
|||
'DummyInvalidCallback',
|
||||
)
|
||||
|
||||
# *************************************************************
|
||||
# *************************************************************
|
||||
# ********************** Core callbacks ***********************
|
||||
# *************************************************************
|
||||
# *************************************************************
|
||||
|
||||
# *************************************************************
|
||||
# **************** Save as foo callback ***********************
|
||||
# *************************************************************
|
||||
|
|
@ -51,3 +65,46 @@ class DummyInvalidCallback(FormCallback):
|
|||
|
||||
|
||||
form_callback_registry.register(DummyInvalidCallback)
|
||||
|
||||
# *************************************************************
|
||||
# *************************************************************
|
||||
# ****************** DRF integration callbacks ****************
|
||||
# *************************************************************
|
||||
# *************************************************************
|
||||
|
||||
|
||||
# *************************************************************
|
||||
# **************** Save as foo callback ***********************
|
||||
# *************************************************************
|
||||
|
||||
|
||||
class DRFSaveAsFooItem(IntegrationFormCallback):
|
||||
"""Save the form as a foo item, if certain conditions are met."""
|
||||
|
||||
stage = CALLBACK_FORM_VALID
|
||||
integrate_with = INTEGRATE_WITH
|
||||
|
||||
def callback(self, form_entry, request, **kwargs):
|
||||
"""Custom callback login comes here."""
|
||||
logger.debug("Great! Your form is valid!")
|
||||
|
||||
|
||||
integration_form_callback_registry.register(DRFSaveAsFooItem)
|
||||
|
||||
# *************************************************************
|
||||
# **************** Save as foo callback ***********************
|
||||
# *************************************************************
|
||||
|
||||
|
||||
class DRFDummyInvalidCallback(IntegrationFormCallback):
|
||||
"""Saves the form as a foo item, if certain conditions are met."""
|
||||
|
||||
stage = CALLBACK_FORM_INVALID
|
||||
integrate_with = INTEGRATE_WITH
|
||||
|
||||
def callback(self, form_entry, request, **kwargs):
|
||||
"""Custom callback login comes here."""
|
||||
logger.debug("Damn! You've made a mistake, boy!")
|
||||
|
||||
|
||||
integration_form_callback_registry.register(DRFDummyInvalidCallback)
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ INSTALLED_APPS = [
|
|||
'rest_framework', # Django REST framework
|
||||
'fobi.contrib.apps.drf_integration', # DRF integration app
|
||||
|
||||
# Form elements
|
||||
# Form fields
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.boolean',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields'
|
||||
'.checkbox_select_multiple',
|
||||
|
|
@ -427,6 +427,11 @@ INSTALLED_APPS = [
|
|||
'fobi.contrib.apps.drf_integration.form_elements.fields.time',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.url',
|
||||
|
||||
# Presentational elements
|
||||
'fobi.contrib.apps.drf_integration.form_elements.content.content_image',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.content.content_text',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.content.content_video',
|
||||
|
||||
# Form handlers
|
||||
'fobi.contrib.apps.drf_integration.form_handlers.db_store',
|
||||
'fobi.contrib.apps.drf_integration.form_handlers.mail',
|
||||
|
|
@ -463,6 +468,12 @@ PACKAGE_NAME_GRAPPELLI = "grappelli_safe" # Just for tests
|
|||
# }
|
||||
# SOUTH_MIGRATION_MODULES = 'south_migrations'
|
||||
|
||||
# **************************************************************
|
||||
# ********************* Registration settings ******************
|
||||
# **************************************************************
|
||||
|
||||
ACCOUNT_ACTIVATION_DAYS = 7
|
||||
|
||||
# **************************************************************
|
||||
# ************************ Fobi settings ***********************
|
||||
# **************************************************************
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from distutils.version import LooseVersion
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
version = '0.11.1'
|
||||
version = '0.11.4'
|
||||
|
||||
# ***************************************************************************
|
||||
# ************************** Python version *********************************
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
__title__ = 'django-fobi'
|
||||
__version__ = '0.11.1'
|
||||
__build__ = 0x00007c
|
||||
__version__ = '0.11.4'
|
||||
__build__ = 0x00007f
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
|
|
|||
131
src/fobi/base.py
131
src/fobi/base.py
|
|
@ -146,6 +146,9 @@ __all__ = (
|
|||
'IntegrationFormHandlerPlugin',
|
||||
'IntegrationFormHandlerPluginDataStorage',
|
||||
'IntegrationFormHandlerPluginRegistry',
|
||||
'IntegrationFormCallbackRegistry',
|
||||
'IntegrationFormCallback',
|
||||
'integration_form_callback_registry',
|
||||
'run_form_handlers',
|
||||
'run_form_wizard_handlers',
|
||||
'theme_registry',
|
||||
|
|
@ -2060,7 +2063,7 @@ class IntegrationFormHandlerPlugin(BasePlugin):
|
|||
is_hidden = False
|
||||
|
||||
|
||||
class FormCallback(object):
|
||||
class BaseFormCallback(object):
|
||||
"""Base form callback."""
|
||||
|
||||
stage = None
|
||||
|
|
@ -2069,6 +2072,10 @@ class FormCallback(object):
|
|||
"""Constructor."""
|
||||
assert self.stage in CALLBACK_STAGES
|
||||
|
||||
|
||||
class FormCallback(BaseFormCallback):
|
||||
"""Form callback."""
|
||||
|
||||
def _callback(self, form_entry, request, form):
|
||||
"""Callback (internal method).
|
||||
|
||||
|
|
@ -2098,31 +2105,45 @@ class FormCallback(object):
|
|||
"subclass.".format(self.__class__.__name__)
|
||||
)
|
||||
|
||||
# def custom_field_instances_callback(self, integrate_with, form_entry,
|
||||
# request, **kwargs):
|
||||
# """Custom field instances callback.
|
||||
#
|
||||
# :param str integrate_with:
|
||||
# :param fobi.models.FormEntry form_entry: Instance of
|
||||
# ``fobi.models.FormEntry``.
|
||||
# :param django.http.HttpRequest request:
|
||||
# :param kwargs:
|
||||
# """
|
||||
# try:
|
||||
# custom_callback = self.get_custom_field_instance_callback(
|
||||
# integrate_with=integrate_with
|
||||
# )
|
||||
# return custom_callback.callback(
|
||||
# form_entry=form_entry,
|
||||
# request=request,
|
||||
# **kwargs
|
||||
# )
|
||||
# except Exception as err:
|
||||
# logger.debug(
|
||||
# "Error in class %s. Details: %s",
|
||||
# self.__class__.__name__,
|
||||
# str(err)
|
||||
# )
|
||||
|
||||
class IntegrationFormCallback(object):
|
||||
"""Integration form callback."""
|
||||
|
||||
integrate_with = None
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor."""
|
||||
assert self.stage in CALLBACK_STAGES
|
||||
assert self.integrate_with is not None
|
||||
|
||||
def _callback(self, form_entry, request, **kwargs):
|
||||
"""Callback (internal method).
|
||||
|
||||
Calling the ``callback`` method in a safe way.
|
||||
"""
|
||||
try:
|
||||
return self.callback(form_entry, request, **kwargs)
|
||||
except Exception as err:
|
||||
logger.debug(
|
||||
"Error in class %s. Details: %s",
|
||||
self.__class__.__name__,
|
||||
str(err)
|
||||
)
|
||||
|
||||
def callback(self, form_entry, request, **kwargs):
|
||||
"""Callback.
|
||||
|
||||
Custom callback code should be implemented here.
|
||||
|
||||
:param fobi.models.FormEntry form_entry: Instance of
|
||||
``fobi.models.FormEntry``.
|
||||
:param django.http.HttpRequest request:
|
||||
:param django.forms.Form form:
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"You should implement ``callback`` method in your {0} "
|
||||
"subclass.".format(self.__class__.__name__)
|
||||
)
|
||||
|
||||
|
||||
class ClassProperty(property):
|
||||
|
|
@ -2507,6 +2528,61 @@ class FormCallbackRegistry(object):
|
|||
return callbacks
|
||||
|
||||
|
||||
class IntegrationFormCallbackRegistry(object):
|
||||
"""Registry of callbacks for integration plugins.
|
||||
|
||||
Holds callbacks for stages listed in the
|
||||
``fobi.constants.CALLBACK_STAGES``.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor."""
|
||||
self._registry = defaultdict(lambda: defaultdict(list))
|
||||
|
||||
@property
|
||||
def registry(self):
|
||||
return self._registry
|
||||
|
||||
def uidfy(self, cls):
|
||||
"""Makes a UID string from the class given.
|
||||
|
||||
:param mixed cls:
|
||||
:return string:
|
||||
"""
|
||||
return "{0}.{1}".format(cls.__module__, cls.__name__)
|
||||
|
||||
def register(self, cls):
|
||||
"""Registers the plugin in the registry.
|
||||
|
||||
:param mixed cls:
|
||||
"""
|
||||
if not issubclass(cls, IntegrationFormCallback):
|
||||
raise InvalidRegistryItemType(
|
||||
"Invalid item type `{0}` for registry "
|
||||
"`{1}`".format(cls, self.__class__)
|
||||
)
|
||||
if cls in self._registry[cls.integrate_with][cls.stage]:
|
||||
return False
|
||||
else:
|
||||
self._registry[cls.integrate_with][cls.stage].append(cls)
|
||||
return True
|
||||
|
||||
def get_callbacks(self, integrate_with, stage=None):
|
||||
"""Get callbacks for the stage given.
|
||||
|
||||
:param str integrate_with:
|
||||
:param string stage:
|
||||
:return list:
|
||||
"""
|
||||
if stage:
|
||||
return self._registry[integrate_with].get(stage, [])
|
||||
else:
|
||||
callbacks = []
|
||||
for stage_callbacks in self._registry[integrate_with].values():
|
||||
callbacks += stage_callbacks
|
||||
return callbacks
|
||||
|
||||
|
||||
class BasePluginWidgetRegistry(object):
|
||||
"""Registry of plugins widgets (renderers)."""
|
||||
type = None
|
||||
|
|
@ -2630,6 +2706,9 @@ theme_registry = ThemeRegistry()
|
|||
# Register action plugins by calling form_action_plugin_registry.register()
|
||||
form_callback_registry = FormCallbackRegistry()
|
||||
|
||||
# Register action plugins by calling form_action_plugin_registry.register()
|
||||
integration_form_callback_registry = IntegrationFormCallbackRegistry()
|
||||
|
||||
# Register plugin widgets by calling
|
||||
# form_element_plugin_widget_registry.register()
|
||||
form_element_plugin_widget_registry = FormElementPluginWidgetRegistry()
|
||||
|
|
|
|||
|
|
@ -19,6 +19,14 @@ Supported fields
|
|||
----------------
|
||||
The following fields are supported.
|
||||
|
||||
Content (presentational form elements)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
- content_image
|
||||
- content_text
|
||||
- content_video
|
||||
|
||||
Fields
|
||||
~~~~~~
|
||||
- boolean
|
||||
- checkbox_select_multiple
|
||||
- date
|
||||
|
|
@ -52,9 +60,6 @@ The following fields are not supported. Those marked with asterisk are planned
|
|||
to be supported in the upcoming releases.
|
||||
|
||||
- date_drop_down
|
||||
- content_image
|
||||
- content_text
|
||||
- content_video
|
||||
- select_model_object
|
||||
- select_mptt_model_object
|
||||
- select_multiple_model_objects
|
||||
|
|
@ -100,6 +105,9 @@ the core plugins:
|
|||
- fobi.contrib.plugins.form_elements.fields.textarea
|
||||
- fobi.contrib.plugins.form_elements.fields.time
|
||||
- fobi.contrib.plugins.form_elements.fields.url
|
||||
- fobi.contrib.plugins.form_elements.content.content_image
|
||||
- fobi.contrib.plugins.form_elements.content.content_text
|
||||
- fobi.contrib.plugins.form_elements.content.content_video
|
||||
- fobi.contrib.plugins.form_handlers.db_store
|
||||
- fobi.contrib.plugins.form_handlers.http_repost
|
||||
- fobi.contrib.plugins.form_handlers.mail
|
||||
|
|
@ -133,6 +141,9 @@ in the ``INSTALLED_APPS`` as well:
|
|||
- fobi.contrib.apps.drf_integration.form_elements.fields.textarea
|
||||
- fobi.contrib.apps.drf_integration.form_elements.fields.time
|
||||
- fobi.contrib.apps.drf_integration.form_elements.fields.url
|
||||
- fobi.contrib.apps.drf_integration.form_elements.content.content_image
|
||||
- fobi.contrib.apps.drf_integration.form_elements.content.content_text
|
||||
- fobi.contrib.apps.drf_integration.form_elements.content.content_video
|
||||
- fobi.contrib.apps.drf_integration.form_handlers.db_store
|
||||
- fobi.contrib.apps.drf_integration.form_handlers.http_repost
|
||||
- fobi.contrib.apps.drf_integration.form_handlers.mail
|
||||
|
|
@ -165,7 +176,7 @@ See the `example settings file
|
|||
'rest_framework', # Django REST framework
|
||||
'fobi.contrib.apps.drf_integration', # DRF integration app
|
||||
|
||||
# DRF integration form element plugins
|
||||
# DRF integration form element plugins - fields
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.boolean',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.checkbox_select_multiple',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.date',
|
||||
|
|
@ -193,6 +204,11 @@ See the `example settings file
|
|||
'fobi.contrib.apps.drf_integration.form_elements.fields.time',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.url',
|
||||
|
||||
# DRF integration form element plugins - presentational
|
||||
'fobi.contrib.apps.drf_integration.form_elements.content.content_image',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.content.content_text',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.content.content_video',
|
||||
|
||||
# DRF integration form handler plugins
|
||||
'fobi.contrib.apps.drf_integration.form_handlers.db_store',
|
||||
'fobi.contrib.apps.drf_integration.form_handlers.mail',
|
||||
|
|
@ -247,6 +263,51 @@ PUT
|
|||
|
||||
{DATA}
|
||||
|
||||
Callbacks
|
||||
---------
|
||||
Callbacks work just the same way the core callbacks work.
|
||||
|
||||
fobi_form_callbacks.py
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: python
|
||||
|
||||
from fobi.base import (
|
||||
integration_form_callback_registry,
|
||||
IntegrationFormCallback,
|
||||
)
|
||||
|
||||
from fobi.constants import (
|
||||
CALLBACK_BEFORE_FORM_VALIDATION,
|
||||
CALLBACK_FORM_INVALID,
|
||||
CALLBACK_FORM_VALID,
|
||||
CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS,
|
||||
CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA,
|
||||
)
|
||||
|
||||
from fobi.contrib.apps.drf_integration import UID as INTEGRATE_WITH
|
||||
|
||||
|
||||
class DRFSaveAsFooItem(IntegrationFormCallback):
|
||||
"""Save the form as a foo item, if certain conditions are met."""
|
||||
|
||||
stage = CALLBACK_FORM_VALID
|
||||
integrate_with = INTEGRATE_WITH
|
||||
|
||||
def callback(self, form_entry, request, **kwargs):
|
||||
"""Custom callback login comes here."""
|
||||
logger.debug("Great! Your form is valid!")
|
||||
|
||||
|
||||
class DRFDummyInvalidCallback(IntegrationFormCallback):
|
||||
"""Saves the form as a foo item, if certain conditions are met."""
|
||||
|
||||
stage = CALLBACK_FORM_INVALID
|
||||
integrate_with = INTEGRATE_WITH
|
||||
|
||||
def callback(self, form_entry, request, **kwargs):
|
||||
"""Custom callback login comes here."""
|
||||
logger.debug("Damn! You've made a mistake, boy!")
|
||||
|
||||
Testing
|
||||
-------
|
||||
To test Django REST framework integration package only, run the following
|
||||
|
|
@ -264,5 +325,4 @@ or use plain Django tests:
|
|||
|
||||
Limitations
|
||||
-----------
|
||||
Due to limits of the API interface, certain fields are not available
|
||||
yet (presentational fields).
|
||||
Certain fields are not available yet (relational fields).
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ Must haves
|
|||
instances. Do it this way and not the other way, since things get
|
||||
complicated when we start to deal with wizards.
|
||||
+ Find out how to handle further the submitted data? It should be in
|
||||
accordance with fobi concepts of loosely couple parts. After successful
|
||||
submission, the fobi form callbacks, handlers and that kind of things
|
||||
accordance with ``fobi`` concepts of loosely couple parts. After successful
|
||||
submission, the ``fobi`` form callbacks, handlers and that kind of things
|
||||
should be fired for the given form entry. Thus, it should likely be the
|
||||
same in this case. Probably each CustomFieldInstancePlugin should get
|
||||
a method ``drf_submit_plugin_form_data``, which should mimic the
|
||||
|
|
@ -27,19 +27,19 @@ Must haves
|
|||
+ Fixed Python3 issues with max_length for text fields.
|
||||
+ In decimal plugin, if any of the values are None, don't try to cast them
|
||||
into Decimal.
|
||||
- Add ``date_drop_down`` plugin.
|
||||
+ Fix this https://github.com/barseghyanartur/django-fobi/blob/master/src/fobi/contrib/apps/drf_integration/views.py#L151
|
||||
It should not be form = ... but serializer = ...
|
||||
|
||||
Should haves
|
||||
------------
|
||||
+ Find why HiddenInput tests fail (in terms of Django REST framework it's
|
||||
a read-only field).
|
||||
- Add custom field instance callback for handling data of the custom field
|
||||
instances. Do it this way and not the other way, since things get
|
||||
complicated when we start to deal with wizards.
|
||||
- Add more fields (relation- and presentational- fields).
|
||||
+ Add Integration form callbacks for handling data of the integration plugins.
|
||||
- Add ``date_drop_down`` plugin.
|
||||
- Add more fields (relation fields).
|
||||
- Think of what to do with presentational fields (perhaps just display?)
|
||||
- Somehow, the `file` plugin data, when submitted, isn't shown properly in the
|
||||
posted data (by DRF), although is posted 100% correctly.
|
||||
- Somehow, the ``file`` plugin data, when submitted, isn't shown properly in
|
||||
the posted data (by DRF), although is posted 100% correctly.
|
||||
- In the API form view, use memoize technique or cache the value somehow to
|
||||
reduce the number of queries.
|
||||
|
||||
|
|
@ -49,4 +49,4 @@ Could haves
|
|||
|
||||
Would haves
|
||||
-----------
|
||||
- Remove codebin.py at the end.
|
||||
+ Remove codebin.py at the end.
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import copy
|
|||
import logging
|
||||
|
||||
from ....base import (
|
||||
IntegrationFormElementPluginProcessor,
|
||||
# form_callback_registry,
|
||||
get_ignorable_form_fields,
|
||||
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
|
||||
|
||||
|
|
@ -131,27 +131,29 @@ class DRFSubmitPluginFormDataMixin(object):
|
|||
"""
|
||||
|
||||
|
||||
# def fire_form_callbacks(form_entry, request, serializer, stage=None):
|
||||
# """Fire 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 = form_callback_registry.get_callbacks(stage=stage)
|
||||
# for CallbackClass in callbacks:
|
||||
# callback = CallbackClass()
|
||||
# updated_serializer = callback.custom_field_instances_callback(
|
||||
# integrate_with=UID,
|
||||
# form_entry=form_entry,
|
||||
# request=request,
|
||||
# serializer=serializer,
|
||||
# )
|
||||
# if updated_serializer:
|
||||
# serializer = updated_serializer
|
||||
# return serializer
|
||||
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,
|
||||
|
|
@ -232,17 +234,17 @@ def submit_plugin_form_data(form_entry,
|
|||
)
|
||||
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
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import copy
|
||||
|
||||
# import six
|
||||
#
|
||||
# from django.utils.safestring import mark_safe
|
||||
import six
|
||||
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from rest_framework.fields import (
|
||||
# Field,
|
||||
# empty,
|
||||
Field,
|
||||
empty,
|
||||
MultipleChoiceField,
|
||||
)
|
||||
|
||||
|
|
@ -16,7 +16,11 @@ __author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
|||
__copyright__ = '2016-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'ContentImageField',
|
||||
'ContentTextField',
|
||||
'ContentVideoField',
|
||||
'MultipleChoiceWithMaxField',
|
||||
'NoneField',
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -43,3 +47,49 @@ class MultipleChoiceWithMaxField(MultipleChoiceField):
|
|||
MultipleChoiceWithMaxField,
|
||||
self
|
||||
).to_internal_value(data)
|
||||
|
||||
|
||||
class NoneField(Field):
|
||||
"""NoneField."""
|
||||
|
||||
default_error_messages = {}
|
||||
initial = ''
|
||||
default_empty_html = ''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.allow_blank = True
|
||||
self.trim_whitespace = kwargs.pop('trim_whitespace', True)
|
||||
self.raw_data = kwargs.pop('raw_data', {})
|
||||
super(NoneField, self).__init__(**kwargs)
|
||||
|
||||
def run_validation(self, data=empty):
|
||||
return ''
|
||||
|
||||
def to_internal_value(self, data):
|
||||
# We're lenient with allowing basic numerics to be coerced into
|
||||
# strings, but other types should fail. Eg. unclear if booleans
|
||||
# should represent as `true` or `True`, and composites such as lists
|
||||
# are likely user error.
|
||||
_not_isinstance_str_int_float = not isinstance(
|
||||
data, six.string_types + six.integer_types + (float,)
|
||||
)
|
||||
if isinstance(data, bool) or _not_isinstance_str_int_float:
|
||||
self.fail('invalid')
|
||||
value = six.text_type(data)
|
||||
return value.strip() if self.trim_whitespace else value
|
||||
|
||||
def to_representation(self, value):
|
||||
return mark_safe(six.text_type(value))
|
||||
|
||||
|
||||
class ContentTextField(NoneField):
|
||||
"""Content text field."""
|
||||
|
||||
|
||||
class ContentImageField(NoneField):
|
||||
"""Content image field."""
|
||||
|
||||
|
||||
class ContentVideoField(NoneField):
|
||||
"""Content video field."""
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
====================================================================
|
||||
fobi.contrib.apps.drf_integration.form_elements.fields.content_image
|
||||
====================================================================
|
||||
A ``django-fobi`` ContentImage plugin for integration with
|
||||
``Django REST framework``. Makes use of the
|
||||
``fobi.contrib.apps.drf_integration.fields.ContentImage``.
|
||||
|
||||
Installation
|
||||
============
|
||||
1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.content_image``
|
||||
to the ``INSTALLED_APPS`` in your ``settings.py``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.content_image',
|
||||
# ...
|
||||
)
|
||||
|
||||
2. In the terminal type:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./manage.py fobi_sync_plugins
|
||||
|
||||
3. Assign appropriate permissions to the target users/groups to be using
|
||||
the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_image'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('default_app_config', 'UID',)
|
||||
|
||||
default_app_config = 'fobi.contrib.apps.drf_integration.form_elements.' \
|
||||
'content.content_image.apps.Config'
|
||||
|
||||
UID = 'content_image'
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_image.apps'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
||||
try:
|
||||
__all__ = ('Config',)
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
class Config(AppConfig):
|
||||
name = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_image'
|
||||
label = 'fobi_contrib_apps_drf_integration_form_elements_content_' \
|
||||
'content_image'
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .......base import IntegrationFormElementPlugin
|
||||
from .... import UID as INTEGRATE_WITH_UID
|
||||
from ....base import (
|
||||
DRFIntegrationFormElementPluginProcessor,
|
||||
DRFSubmitPluginFormDataMixin,
|
||||
)
|
||||
from ....fields import ContentImageField
|
||||
from . import UID
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_image.base'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('ContentImagePlugin',)
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ContentImagePlugin(IntegrationFormElementPlugin,
|
||||
DRFSubmitPluginFormDataMixin):
|
||||
"""CharField plugin."""
|
||||
|
||||
uid = UID
|
||||
integrate_with = INTEGRATE_WITH_UID
|
||||
name = _("Content image")
|
||||
group = _("Content")
|
||||
|
||||
def get_custom_field_instances(self,
|
||||
form_element_plugin,
|
||||
request=None,
|
||||
form_entry=None,
|
||||
form_element_entries=None,
|
||||
has_value=None,
|
||||
**kwargs):
|
||||
"""Get form field instances."""
|
||||
|
||||
rendered_image = form_element_plugin.get_rendered_image()
|
||||
|
||||
field_kwargs = {
|
||||
'initial': rendered_image,
|
||||
'default': rendered_image,
|
||||
'required': False,
|
||||
'label': '',
|
||||
'read_only': True,
|
||||
'raw_data': form_element_plugin.get_raw_data(),
|
||||
}
|
||||
|
||||
return [
|
||||
DRFIntegrationFormElementPluginProcessor(
|
||||
field_class=ContentImageField,
|
||||
field_kwargs=field_kwargs
|
||||
)
|
||||
]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from .......base import integration_form_element_plugin_registry
|
||||
from .base import ContentImagePlugin
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_image.fobi_integration_form_elements'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('ContentImagePlugin',)
|
||||
|
||||
|
||||
integration_form_element_plugin_registry.register(ContentImagePlugin)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
===================================================================
|
||||
fobi.contrib.apps.drf_integration.form_elements.fields.content_text
|
||||
===================================================================
|
||||
A ``django-fobi`` ContentText plugin for integration with
|
||||
``Django REST framework``. Makes use of the
|
||||
``fobi.contrib.apps.drf_integration.fields.ContentText``.
|
||||
|
||||
Installation
|
||||
============
|
||||
1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.content_text``
|
||||
to the ``INSTALLED_APPS`` in your ``settings.py``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.content_text',
|
||||
# ...
|
||||
)
|
||||
|
||||
2. In the terminal type:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./manage.py fobi_sync_plugins
|
||||
|
||||
3. Assign appropriate permissions to the target users/groups to be using
|
||||
the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_text'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('default_app_config', 'UID',)
|
||||
|
||||
default_app_config = 'fobi.contrib.apps.drf_integration.form_elements.' \
|
||||
'content.content_text.apps.Config'
|
||||
|
||||
UID = 'content_text'
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_text.apps'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
||||
try:
|
||||
__all__ = ('Config',)
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
class Config(AppConfig):
|
||||
name = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_text'
|
||||
label = 'fobi_contrib_apps_drf_integration_form_elements_content_' \
|
||||
'content_text'
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .......base import IntegrationFormElementPlugin
|
||||
from .... import UID as INTEGRATE_WITH_UID
|
||||
from ....base import (
|
||||
DRFIntegrationFormElementPluginProcessor,
|
||||
DRFSubmitPluginFormDataMixin,
|
||||
)
|
||||
from ....fields import ContentTextField
|
||||
from . import UID
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_text.base'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('ContentTextPlugin',)
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ContentTextPlugin(IntegrationFormElementPlugin,
|
||||
DRFSubmitPluginFormDataMixin):
|
||||
"""CharField plugin."""
|
||||
|
||||
uid = UID
|
||||
integrate_with = INTEGRATE_WITH_UID
|
||||
name = _("Content text")
|
||||
group = _("Content")
|
||||
|
||||
def get_custom_field_instances(self,
|
||||
form_element_plugin,
|
||||
request=None,
|
||||
form_entry=None,
|
||||
form_element_entries=None,
|
||||
has_value=None,
|
||||
**kwargs):
|
||||
"""Get form field instances."""
|
||||
|
||||
rendered_text = form_element_plugin.get_rendered_text()
|
||||
|
||||
LOGGER.debug(rendered_text)
|
||||
|
||||
field_kwargs = {
|
||||
'initial': rendered_text,
|
||||
'default': rendered_text,
|
||||
'required': False,
|
||||
'label': '',
|
||||
'read_only': True,
|
||||
'raw_data': form_element_plugin.get_raw_data(),
|
||||
}
|
||||
|
||||
return [
|
||||
DRFIntegrationFormElementPluginProcessor(
|
||||
field_class=ContentTextField,
|
||||
field_kwargs=field_kwargs
|
||||
)
|
||||
]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from .......base import integration_form_element_plugin_registry
|
||||
from .base import ContentTextPlugin
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_text.fobi_integration_form_elements'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('ContentTextPlugin',)
|
||||
|
||||
|
||||
integration_form_element_plugin_registry.register(ContentTextPlugin)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
====================================================================
|
||||
fobi.contrib.apps.drf_integration.form_elements.fields.content_video
|
||||
====================================================================
|
||||
A ``django-fobi`` ContentVideo plugin for integration with
|
||||
``Django REST framework``. Makes use of the
|
||||
``fobi.contrib.apps.drf_integration.fields.ContentVideo``.
|
||||
|
||||
Installation
|
||||
============
|
||||
1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.content_video``
|
||||
to the ``INSTALLED_APPS`` in your ``settings.py``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.content_video',
|
||||
# ...
|
||||
)
|
||||
|
||||
2. In the terminal type:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./manage.py fobi_sync_plugins
|
||||
|
||||
3. Assign appropriate permissions to the target users/groups to be using
|
||||
the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_video'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('default_app_config', 'UID',)
|
||||
|
||||
default_app_config = 'fobi.contrib.apps.drf_integration.form_elements.' \
|
||||
'content.content_video.apps.Config'
|
||||
|
||||
UID = 'content_video'
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_video.apps'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
||||
try:
|
||||
__all__ = ('Config',)
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
class Config(AppConfig):
|
||||
name = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_video'
|
||||
label = 'fobi_contrib_apps_drf_integration_form_elements_content_' \
|
||||
'content_video'
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .......base import IntegrationFormElementPlugin
|
||||
from .... import UID as INTEGRATE_WITH_UID
|
||||
from ....base import (
|
||||
DRFIntegrationFormElementPluginProcessor,
|
||||
DRFSubmitPluginFormDataMixin,
|
||||
)
|
||||
from ....fields import ContentVideoField
|
||||
from . import UID
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_video.base'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('ContentVideoPlugin',)
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ContentVideoPlugin(IntegrationFormElementPlugin,
|
||||
DRFSubmitPluginFormDataMixin):
|
||||
"""CharField plugin."""
|
||||
|
||||
uid = UID
|
||||
integrate_with = INTEGRATE_WITH_UID
|
||||
name = _("Content image")
|
||||
group = _("Content")
|
||||
|
||||
def get_custom_field_instances(self,
|
||||
form_element_plugin,
|
||||
request=None,
|
||||
form_entry=None,
|
||||
form_element_entries=None,
|
||||
has_value=None,
|
||||
**kwargs):
|
||||
"""Get form field instances."""
|
||||
rendered_video = form_element_plugin.get_rendered_video()
|
||||
|
||||
field_kwargs = {
|
||||
'initial': rendered_video,
|
||||
'default': rendered_video,
|
||||
'required': False,
|
||||
'label': '',
|
||||
'read_only': True,
|
||||
'raw_data': form_element_plugin.get_raw_data(),
|
||||
}
|
||||
|
||||
return [
|
||||
DRFIntegrationFormElementPluginProcessor(
|
||||
field_class=ContentVideoField,
|
||||
field_kwargs=field_kwargs
|
||||
)
|
||||
]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from .......base import integration_form_element_plugin_registry
|
||||
from .base import ContentVideoPlugin
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.form_elements.content.' \
|
||||
'content_video.fobi_integration_form_elements'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('ContentVideoPlugin',)
|
||||
|
||||
|
||||
integration_form_element_plugin_registry.register(ContentVideoPlugin)
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
===============================================================
|
||||
fobi.contrib.apps.drf_integration.form_elements.fields.datetime
|
||||
===============================================================
|
||||
==============================================================
|
||||
fobi.contrib.apps.drf_integration.form_elements.fields.decimal
|
||||
==============================================================
|
||||
A ``django-fobi`` DecimalField plugin for integration with
|
||||
``Django REST framework``. Makes use of the
|
||||
``rest_framework.fields.DateTimeField``.
|
||||
``rest_framework.fields.DecimalField``.
|
||||
|
||||
Installation
|
||||
============
|
||||
1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.datetime`` to
|
||||
1. Add ``fobi.contrib.apps.drf_integration.form_elements.fields.decimal`` to
|
||||
the ``INSTALLED_APPS`` in your ``settings.py``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.datetime',
|
||||
'fobi.contrib.apps.drf_integration.form_elements.fields.decimal',
|
||||
# ...
|
||||
)
|
||||
|
||||
|
|
|
|||
63
src/fobi/contrib/apps/drf_integration/metadata.py
Normal file
63
src/fobi/contrib/apps/drf_integration/metadata.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import copy
|
||||
|
||||
from rest_framework.metadata import SimpleMetadata
|
||||
from rest_framework.utils.field_mapping import ClassLookupDict
|
||||
|
||||
from .fields import (
|
||||
MultipleChoiceWithMaxField,
|
||||
ContentImageField,
|
||||
ContentTextField,
|
||||
ContentVideoField,
|
||||
)
|
||||
|
||||
__title__ = 'fobi.contrib.apps.drf_integration.metadata'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2016-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'FobiMetaData',
|
||||
)
|
||||
|
||||
|
||||
class FobiMetaData(SimpleMetadata):
|
||||
"""Meta data for better representation of the form elements."""
|
||||
|
||||
__mapping = copy.copy(SimpleMetadata.label_lookup.mapping)
|
||||
__mapping.update(
|
||||
{
|
||||
MultipleChoiceWithMaxField: 'multiple choice',
|
||||
ContentImageField: 'content',
|
||||
ContentTextField: 'content',
|
||||
ContentVideoField: 'content',
|
||||
}
|
||||
)
|
||||
|
||||
label_lookup = ClassLookupDict(__mapping)
|
||||
|
||||
def get_field_info(self, field):
|
||||
"""Get field info.
|
||||
|
||||
Given an instance of a serializer field, return a dictionary
|
||||
of metadata about it.
|
||||
"""
|
||||
field_info = super(FobiMetaData, self).get_field_info(field)
|
||||
if isinstance(
|
||||
field,
|
||||
(ContentTextField, ContentImageField, ContentVideoField)
|
||||
):
|
||||
field_info['type'] = 'content'
|
||||
|
||||
if isinstance(field, ContentTextField):
|
||||
field_info['contenttype'] = 'text'
|
||||
field_info['content'] = field.initial
|
||||
field_info['raw'] = field.raw_data
|
||||
elif isinstance(field, ContentImageField):
|
||||
field_info['contenttype'] = 'image'
|
||||
field_info['content'] = field.initial
|
||||
field_info['raw'] = field.raw_data
|
||||
else:
|
||||
field_info['contenttype'] = 'video'
|
||||
field_info['content'] = field.initial
|
||||
field_info['raw'] = field.raw_data
|
||||
|
||||
return field_info
|
||||
|
|
@ -17,11 +17,12 @@ from ....constants import (
|
|||
from ....models import FormEntry
|
||||
|
||||
from .base import (
|
||||
# fire_form_callbacks,
|
||||
fire_form_callbacks,
|
||||
run_form_handlers,
|
||||
submit_plugin_form_data,
|
||||
)
|
||||
from .dynamic import get_declared_fields
|
||||
from .metadata import FobiMetaData
|
||||
from .serializers import FormEntrySerializer
|
||||
from .utils import get_serializer_class
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ class FobiFormEntryViewSet(
|
|||
permission_classes = [permissions.AllowAny]
|
||||
lookup_field = 'slug'
|
||||
lookup_url_kwarg = 'slug'
|
||||
metadata_class = FobiMetaData
|
||||
|
||||
def has_value(self):
|
||||
return None if self.action == 'metadata' else True
|
||||
|
|
@ -147,13 +149,13 @@ class FobiFormEntryViewSet(
|
|||
# Try to fetch only once.
|
||||
form_element_entries = form_entry.formelemententry_set.all()
|
||||
|
||||
# # Fire form valid before submit plugin data
|
||||
# form = fire_form_callbacks(
|
||||
# form_entry=form_entry,
|
||||
# request=request,
|
||||
# form=form,
|
||||
# stage=CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA
|
||||
# )
|
||||
# Fire form valid before submit plugin data
|
||||
serializer = fire_form_callbacks(
|
||||
form_entry=form_entry,
|
||||
request=request,
|
||||
serializer=serializer,
|
||||
stage=CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA
|
||||
)
|
||||
|
||||
# Fire plugin processors
|
||||
serializer = submit_plugin_form_data(
|
||||
|
|
@ -162,10 +164,13 @@ class FobiFormEntryViewSet(
|
|||
serializer=serializer
|
||||
)
|
||||
|
||||
# # Fire form valid callbacks
|
||||
# form = fire_form_callbacks(form_entry=form_entry,
|
||||
# request=request, form=form,
|
||||
# stage=CALLBACK_FORM_VALID)
|
||||
# Fire form valid callbacks
|
||||
serializer = fire_form_callbacks(
|
||||
form_entry=form_entry,
|
||||
request=request,
|
||||
serializer=serializer,
|
||||
stage=CALLBACK_FORM_VALID
|
||||
)
|
||||
|
||||
# Run all handlers
|
||||
handler_responses, handler_errors = run_form_handlers(
|
||||
|
|
@ -187,9 +192,9 @@ class FobiFormEntryViewSet(
|
|||
)
|
||||
|
||||
# Fire post handler callbacks
|
||||
# fire_form_callbacks(
|
||||
# form_entry=form_entry,
|
||||
# request=request,
|
||||
# form=form,
|
||||
# stage=CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS
|
||||
# )
|
||||
fire_form_callbacks(
|
||||
form_entry=form_entry,
|
||||
request=request,
|
||||
serializer=serializer,
|
||||
stage=CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from collections import OrderedDict
|
||||
from uuid import uuid4
|
||||
|
||||
from django.conf import settings
|
||||
|
|
@ -56,6 +57,20 @@ class ContentImagePlugin(FormElementPlugin):
|
|||
)
|
||||
return self.get_cloned_plugin_data(update={'file': cloned_image})
|
||||
|
||||
def get_raw_data(self):
|
||||
"""Get raw data.
|
||||
|
||||
Might be used in integration plugins.
|
||||
"""
|
||||
return OrderedDict(
|
||||
(
|
||||
('file', "{}{}".format(settings.MEDIA_URL, self.data.file)),
|
||||
('alt', self.data.alt),
|
||||
('fit_method', self.data.fit_method),
|
||||
('size', self.data.size),
|
||||
)
|
||||
)
|
||||
|
||||
def get_rendered_image(self):
|
||||
"""Get rendered image."""
|
||||
width, height = self.data.size.split('x')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from collections import OrderedDict
|
||||
from uuid import uuid4
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
|
@ -34,6 +36,26 @@ class ContentTextPlugin(FormElementPlugin):
|
|||
"""
|
||||
self.data.name = "{0}_{1}".format(self.uid, uuid4())
|
||||
|
||||
def get_raw_data(self):
|
||||
"""Get raw data.
|
||||
|
||||
Might be used in integration plugins.
|
||||
"""
|
||||
return OrderedDict(
|
||||
(
|
||||
('text', self.data.text),
|
||||
)
|
||||
)
|
||||
|
||||
def get_rendered_text(self):
|
||||
"""Get rendered image."""
|
||||
|
||||
context = {
|
||||
'plugin': self,
|
||||
}
|
||||
rendered_text = render_to_string('content_image/render.html', context)
|
||||
return rendered_text
|
||||
|
||||
def get_form_field_instances(self, request=None, form_entry=None,
|
||||
form_element_entries=None, **kwargs):
|
||||
"""Get form field instances."""
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from collections import OrderedDict
|
||||
from uuid import uuid4
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
|
@ -35,14 +36,33 @@ class ContentVideoPlugin(FormElementPlugin):
|
|||
"""
|
||||
self.data.name = "{0}_{1}".format(self.uid, uuid4())
|
||||
|
||||
def get_raw_data(self):
|
||||
"""Get raw data.
|
||||
|
||||
Might be used in integration plugins.
|
||||
"""
|
||||
return OrderedDict(
|
||||
(
|
||||
('title', self.data.title),
|
||||
('url', self.data.url),
|
||||
('size', self.data.size),
|
||||
)
|
||||
)
|
||||
|
||||
def get_rendered_video(self):
|
||||
"""Get rendered video.
|
||||
|
||||
Might be used in integration plugins.
|
||||
"""
|
||||
width, height = self.data.size.split('x')
|
||||
return render_video(self.data.url, width, height)
|
||||
|
||||
def get_form_field_instances(self, request=None, form_entry=None,
|
||||
form_element_entries=None, **kwargs):
|
||||
"""Get form field instances."""
|
||||
width, height = self.data.size.split('x')
|
||||
|
||||
field_kwargs = {
|
||||
'initial': '<div class="video-wrapper">{0}</div>'.format(
|
||||
render_video(self.data.url, width, height)
|
||||
self.get_rendered_video()
|
||||
),
|
||||
'required': False,
|
||||
'label': '',
|
||||
|
|
|
|||
Loading…
Reference in a new issue