mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-11 06:13:10 +00:00
Merge branch 'master' into wagtail/integration
This commit is contained in:
commit
d84977fe96
25 changed files with 351 additions and 219 deletions
|
|
@ -15,6 +15,22 @@ are used for versioning (schema follows below):
|
|||
0.3.4 to 0.4).
|
||||
- All backwards incompatible changes are mentioned in this document.
|
||||
|
||||
0.10.8
|
||||
------
|
||||
yyyy-mm-dd (not yet released)
|
||||
|
||||
- Documentation fixes.
|
||||
- PEP8 code fixes.
|
||||
- Minor setup fixes related to moved screen-shots file.
|
||||
- Added helper scripts to test with Firefox in headless mode. Describe
|
||||
testing with Firefox in headless mode in documentation.
|
||||
|
||||
0.10.7
|
||||
------
|
||||
2017-03-13
|
||||
|
||||
- Several Django deprecation/moves fixes for better future compatibility.
|
||||
|
||||
0.10.6
|
||||
------
|
||||
2017-02-14
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ Installation and configuration
|
|||
------------------------------
|
||||
Install the package in your environment.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. code-block:: none
|
||||
.. code-block:: sh
|
||||
|
||||
pip install django-fobi
|
||||
|
||||
INSTALLED_APPS
|
||||
^^^^^^^^^^^^^^
|
||||
Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your
|
||||
`settings` module.
|
||||
``settings`` module.
|
||||
|
||||
1. The core.
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your
|
|||
<https://github.com/barseghyanartur/django-fobi/tree/stable/src/fobi/contrib/plugins/form_elements/security/recaptcha/>`_
|
||||
would require additional packages to be installed. If so, make sure to have
|
||||
installed and configured those dependencies prior adding the dependant
|
||||
add-ons to the `settings` module.
|
||||
add-ons to the ``settings`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
'easy_thumbnails', # Required by `content_image` plugin
|
||||
'easy_thumbnails', # Required by `content_image` plugin
|
||||
'fobi.contrib.plugins.form_elements.content.content_image',
|
||||
'fobi.contrib.plugins.form_elements.content.content_text',
|
||||
'fobi.contrib.plugins.form_elements.content.content_video',
|
||||
|
|
@ -145,7 +145,7 @@ Putting all together, you would have something like this.
|
|||
'fobi.contrib.plugins.form_elements.fields.url',
|
||||
|
||||
# Form element plugins
|
||||
'easy_thumbnails', # Required by `content_image` plugin
|
||||
'easy_thumbnails', # Required by ``content_image`` plugin
|
||||
'fobi.contrib.plugins.form_elements.content.content_image',
|
||||
'fobi.contrib.plugins.form_elements.content.content_text',
|
||||
'fobi.contrib.plugins.form_elements.content.content_video',
|
||||
|
|
@ -162,21 +162,21 @@ TEMPLATE_CONTEXT_PROCESSORS
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Add ``django.core.context_processors.request`` and
|
||||
``fobi.context_processors.theme`` to ``TEMPLATE_CONTEXT_PROCESSORS`` of
|
||||
your `settings` module.
|
||||
your ``settings`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
# ...
|
||||
"django.core.context_processors.request",
|
||||
"fobi.context_processors.theme", # Obligatory
|
||||
"fobi.context_processors.dynamic_values", # Optional
|
||||
"fobi.context_processors.theme", # Obligatory
|
||||
"fobi.context_processors.dynamic_values", # Optional
|
||||
# ...
|
||||
)
|
||||
|
||||
urlpatterns
|
||||
^^^^^^^^^^^
|
||||
Add the following line to ``urlpatterns`` of your `urls` module.
|
||||
Add the following line to ``urlpatterns`` of your ``urls`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -201,21 +201,21 @@ Update the database
|
|||
1. First you should be syncing/migrating the database. Depending on your
|
||||
Django version and migration app, this step may vary. Typically as follows:
|
||||
|
||||
.. code-block:: none
|
||||
.. code-block:: sh
|
||||
|
||||
$ ./manage.py syncdb
|
||||
$ ./manage.py migrate --fake-initial
|
||||
./manage.py syncdb
|
||||
./manage.py migrate --fake-initial
|
||||
|
||||
2. Sync installed ``fobi`` plugins. Go to terminal and type the following
|
||||
command.
|
||||
|
||||
.. code-block:: none
|
||||
.. code-block:: sh
|
||||
|
||||
$ ./manage.py fobi_sync_plugins
|
||||
./manage.py fobi_sync_plugins
|
||||
|
||||
Specify the active theme
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Specify the default theme in your `settings` module.
|
||||
Specify the default theme in your ``settings`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
|||
118
README.rst
118
README.rst
|
|
@ -302,8 +302,9 @@ Add the following line to urlpatterns of your `urls` module.
|
|||
url(r'^fobi/', include('fobi.urls.edit')),
|
||||
|
||||
Note, that some plugins require additional URL includes. For instance, if you
|
||||
listed the `fobi.contrib.plugins.form_handlers.db_store` form handler plugin
|
||||
in the ``INSTALLED_APPS``, you should mention the following in `urls` module.
|
||||
listed the ``fobi.contrib.plugins.form_handlers.db_store`` form handler plugin
|
||||
in the ``INSTALLED_APPS``, you should mention the following in ``urls``
|
||||
module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -344,8 +345,8 @@ There are several properties, each textarea should have. They are:
|
|||
- `required` (bool): Flag, which tells us whether the field is required or
|
||||
optional.
|
||||
|
||||
Let's name that plugin `sample_textarea`. The plugin directory should then have
|
||||
the following structure.
|
||||
Let's name that plugin ``sample_textarea``. The plugin directory should then
|
||||
have the following structure.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
|
|
@ -368,7 +369,7 @@ Define and register the form element plugin
|
|||
-------------------------------------------
|
||||
Step by step review of a how to create and register a plugin and plugin
|
||||
widgets. Note, that `django-fobi` auto-discovers your plugins if you place
|
||||
them into a file named `fobi_form_elements.py` of any Django app listed in
|
||||
them into a file named ``fobi_form_elements.py`` of any Django app listed in
|
||||
``INSTALLED_APPS`` of your Django projects' settings module.
|
||||
|
||||
path/to/sample_textarea/fobi_form_elements.py
|
||||
|
|
@ -475,11 +476,11 @@ path/to/sample_textarea/forms.py
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Why to have another file for defining forms? Just to keep the code clean and
|
||||
less messy, although you could perfectly define all your plugin forms in the
|
||||
module `fobi_form_elements.py`, it's recommended to keep it separate.
|
||||
module ``fobi_form_elements.py``, it's recommended to keep it separate.
|
||||
|
||||
Take into consideration, that `forms.py` is not an auto-discovered file pattern.
|
||||
All your form element plugins should be registered in modules named
|
||||
`fobi_form_elements.py`.
|
||||
Take into consideration, that ``forms.py`` is not an auto-discovered file
|
||||
pattern. All your form element plugins should be registered in modules named
|
||||
``fobi_form_elements.py``.
|
||||
|
||||
Required imports.
|
||||
|
||||
|
|
@ -631,7 +632,7 @@ Do check the source code as example.
|
|||
|
||||
Define and register the form handler plugin
|
||||
-------------------------------------------
|
||||
Let's name that plugin `sample_mail`. The plugin directory should then have
|
||||
Let's name that plugin ``sample_mail``. The plugin directory should then have
|
||||
the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
|
@ -704,11 +705,11 @@ plugin is configurable, it should have a form.
|
|||
|
||||
Why to have another file for defining forms? Just to keep the code clean and
|
||||
less messy, although you could perfectly define all your plugin forms in the
|
||||
module `fobi_form_handlers.py`, it's recommended to keep it separate.
|
||||
module ``fobi_form_handlers.py``, it's recommended to keep it separate.
|
||||
|
||||
Take into consideration, that `forms.py` is not an auto-discovered file pattern.
|
||||
All your form handler plugins should be registered in modules named
|
||||
`fobi_form_handlers.py`.
|
||||
Take into consideration, that ``forms.py`` is not an auto-discovered file
|
||||
pattern. All your form handler plugins should be registered in modules named
|
||||
``fobi_form_handlers.py``.
|
||||
|
||||
Required imports.
|
||||
|
||||
|
|
@ -837,8 +838,8 @@ existing MailChimp forms into `django-fobi`.
|
|||
|
||||
Define and register the form importer plugin
|
||||
--------------------------------------------
|
||||
Let's name that plugin `sample_importer`. The plugin directory should then have
|
||||
the following structure.
|
||||
Let's name that plugin ``sample_importer``. The plugin directory should then
|
||||
have the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
|
@ -938,7 +939,7 @@ Required imports.
|
|||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from sample_service_api import sample_api # Just an imaginary API client
|
||||
from sample_service_api import sample_api # Just an imaginary API client
|
||||
|
||||
Defining the form for Sample importer plugin.
|
||||
|
||||
|
|
@ -988,7 +989,8 @@ Required imports.
|
|||
from formtools.wizard.views import SessionWizardView
|
||||
|
||||
from path.to.sample_importer.forms import (
|
||||
SampleImporterStep1Form, SampleImporterStep2Form
|
||||
SampleImporterStep1Form,
|
||||
SampleImporterStep2Form,
|
||||
)
|
||||
|
||||
Defining the wizard view for Sample importer plugin.
|
||||
|
|
@ -1076,9 +1078,8 @@ Creating a form callback
|
|||
Form callbacks are additional hooks, that are executed on various stages of
|
||||
the form submission.
|
||||
|
||||
Let's place the callback in the `foo` module. The plugin directory should then
|
||||
have the following
|
||||
structure.
|
||||
Let's place the callback in the ``foo`` module. The plugin directory should
|
||||
then have the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
|
@ -1162,7 +1163,7 @@ themes:
|
|||
- "Foundation 5" theme
|
||||
- "Simple" theme in (with editing interface in style of the Django admin)
|
||||
- "DjangoCMS admin style" theme (which is another simple theme with editing
|
||||
interface in style of `djangocms-admin-style`)
|
||||
interface in style of ``djangocms-admin-style``)
|
||||
|
||||
Obviously, there are two sorts of views when it comes to editing and viewing
|
||||
the form.
|
||||
|
|
@ -1192,7 +1193,7 @@ the "Simple" theme is the best start, since it looks just like django-admin.
|
|||
Create a new theme
|
||||
------------------
|
||||
|
||||
Let's place the theme in the `sample_theme` module. The theme directory
|
||||
Let's place the theme in the ``sample_theme`` module. The theme directory
|
||||
should then have the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
|
@ -1292,7 +1293,7 @@ Registering the ``SampleTheme`` plugin.
|
|||
|
||||
Sometimes you would want to attach additional properties to the theme
|
||||
in order to use them later in templates (remember, current theme object
|
||||
is always available in templates under name `fobi_theme`).
|
||||
is always available in templates under name ``fobi_theme``).
|
||||
|
||||
For such cases you would need to define a variable in your project's settings
|
||||
module, called ``FOBI_CUSTOM_THEME_DATA``. See the following code as example:
|
||||
|
|
@ -1742,7 +1743,7 @@ The following HTML5 fields are supported in corresponding bundled plugins:
|
|||
- placeholder
|
||||
- type
|
||||
|
||||
With the `fobi.contrib.plugins.form_elements.fields.input` support for
|
||||
With the ``fobi.contrib.plugins.form_elements.fields.input`` support for
|
||||
HTML5 fields is extended to the following fields:
|
||||
|
||||
- autocomplete
|
||||
|
|
@ -1769,7 +1770,7 @@ Dynamic initial values
|
|||
It's possible to provide a dynamic initial value for any of the text elements.
|
||||
In order to do that, you should use the build-in context processor or make
|
||||
your own one. The only requirement is that you should store all values that
|
||||
should be exposes in the form as a dict for `fobi_dynamic_values` dictionary
|
||||
should be exposes in the form as a dict for ``fobi_dynamic_values`` dictionary
|
||||
key. Beware, that passing the original request object might be unsafe in
|
||||
many ways. Currently, a stripped down version of the request object is being
|
||||
passed as a context variable.
|
||||
|
|
@ -1793,7 +1794,8 @@ passed as a context variable.
|
|||
}
|
||||
}
|
||||
|
||||
In your GUI, you should be refering to the initial values in the following way:
|
||||
In your GUI, you should be referring to the initial values in the following
|
||||
way:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
|
|
@ -1807,21 +1809,21 @@ Currently, the following variables are available in the
|
|||
|
||||
- request: Stripped HttpRequest object.
|
||||
|
||||
- request.path: A string representing the full path to the requested page,
|
||||
not including the scheme or domain.
|
||||
- request.path: A string representing the full path to the requested
|
||||
page, not including the scheme or domain.
|
||||
|
||||
- request.get_full_path(): Returns the path, plus an appended query string,
|
||||
if applicable.
|
||||
- request.get_full_path(): Returns the path, plus an appended query
|
||||
string, if applicable.
|
||||
|
||||
- request.is_secure(): Returns True if the request is secure; that is, if
|
||||
it was made with HTTPS.
|
||||
- request.is_secure(): Returns True if the request is secure; that
|
||||
is, if it was made with HTTPS.
|
||||
|
||||
- request.is_ajax(): Returns True if the request was made via an
|
||||
XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the
|
||||
string 'XMLHttpRequest'.
|
||||
|
||||
- request.META: A stripped down standard Python dictionary containing the
|
||||
available HTTP headers.
|
||||
- request.META: A stripped down standard Python dictionary containing
|
||||
the available HTTP headers.
|
||||
|
||||
- HTTP_ACCEPT_ENCODING: Acceptable encodings for the response.
|
||||
|
||||
|
|
@ -1833,7 +1835,7 @@ Currently, the following variables are available in the
|
|||
|
||||
- HTTP_USER_AGENT: The client’s user-agent string.
|
||||
|
||||
- QUERY_STRING: The query string, as a single (unparsed) string.
|
||||
- QUERY_STRING: The query string, as a single (un-parsed) string.
|
||||
|
||||
- REMOTE_ADDR: The IP address of the client.
|
||||
|
||||
|
|
@ -1841,9 +1843,9 @@ Currently, the following variables are available in the
|
|||
|
||||
- request.user.email:
|
||||
|
||||
- request.user.get_username(): Returns the username for the user. Since
|
||||
the User model can be swapped out, you should use this method
|
||||
instead of referencing the username attribute directly.
|
||||
- request.user.get_username(): Returns the username for the user.
|
||||
Since the User model can be swapped out, you should use this
|
||||
method instead of referencing the username attribute directly.
|
||||
|
||||
- request.user.get_full_name(): Returns the first_name plus the
|
||||
last_name, with a space in between.
|
||||
|
|
@ -2038,10 +2040,11 @@ install the test requirements:
|
|||
|
||||
Browser tests
|
||||
-------------
|
||||
For browser tests you may choose between Firefox and PhantomJS. PhantomJS is
|
||||
faster, Firefox tests tell you more. Both cases require some effort and both
|
||||
have disadvantages regarding the installation (although once you have them
|
||||
installed they work perfect).
|
||||
For browser tests you may choose between Firefox, headless Firefox and
|
||||
PhantomJS. PhantomJS is faster, headless Firefox is fast as well, but
|
||||
normal Firefox tests tell you more (as you see what exactly happens on the
|
||||
screen). Both cases require some effort and both have disadvantages regarding
|
||||
the installation (although once you have them installed they work perfect).
|
||||
|
||||
Latest versions of Firefox are often not supported by Selenium. Current
|
||||
version of the Selenium for Python (2.53.6) works fine with Firefox 47.
|
||||
|
|
@ -2063,10 +2066,31 @@ Set up Firefox 47
|
|||
|
||||
FIREFOX_BIN_PATH = '/usr/lib/firefox47/firefox'
|
||||
|
||||
If you set ``FIREFOX_BIN_PATH`` to None, system Firefox would be used.
|
||||
If you set to use system Firefox, remove or comment-out the
|
||||
``FIREFOX_BIN_PATH`` setting.
|
||||
|
||||
After that your Selenium tests would work.
|
||||
|
||||
Set up headless Firefox
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. Install ``xvfb`` package which is used to start Firefox in headless mode.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo apt-get install xvfb
|
||||
|
||||
2. Run the tests using headless Firefox.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./scripts/runtests.sh
|
||||
|
||||
Or run tox tests using headless Firefox.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./scripts/tox.sh
|
||||
|
||||
Setup PhantomJS
|
||||
~~~~~~~~~~~~~~~
|
||||
You could also run tests in headless mode (faster). For that you will need
|
||||
|
|
@ -2088,14 +2112,14 @@ PhantomJS.
|
|||
|
||||
PHANTOM_JS_EXECUTABLE_PATH = ""
|
||||
|
||||
If you want to use Firefox for testing, set
|
||||
``PHANTOM_JS_EXECUTABLE_PATH`` to None.
|
||||
If you want to use Firefox for testing, remove or comment-out the
|
||||
``PHANTOM_JS_EXECUTABLE_PATH`` setting.
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
If you get a ``FormElementPluginDoesNotExist`` or a
|
||||
``FormHandlerPluginDoesNotExist`` exception, make sure you have listed your
|
||||
plugin in the `settings` module of your project.
|
||||
plugin in the ``settings`` module of your project.
|
||||
|
||||
License
|
||||
=======
|
||||
|
|
|
|||
118
docs/index.rst
118
docs/index.rst
|
|
@ -302,8 +302,9 @@ Add the following line to urlpatterns of your `urls` module.
|
|||
url(r'^fobi/', include('fobi.urls.edit')),
|
||||
|
||||
Note, that some plugins require additional URL includes. For instance, if you
|
||||
listed the `fobi.contrib.plugins.form_handlers.db_store` form handler plugin
|
||||
in the ``INSTALLED_APPS``, you should mention the following in `urls` module.
|
||||
listed the ``fobi.contrib.plugins.form_handlers.db_store`` form handler plugin
|
||||
in the ``INSTALLED_APPS``, you should mention the following in ``urls``
|
||||
module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -344,8 +345,8 @@ There are several properties, each textarea should have. They are:
|
|||
- `required` (bool): Flag, which tells us whether the field is required or
|
||||
optional.
|
||||
|
||||
Let's name that plugin `sample_textarea`. The plugin directory should then have
|
||||
the following structure.
|
||||
Let's name that plugin ``sample_textarea``. The plugin directory should then
|
||||
have the following structure.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
|
|
@ -368,7 +369,7 @@ Define and register the form element plugin
|
|||
-------------------------------------------
|
||||
Step by step review of a how to create and register a plugin and plugin
|
||||
widgets. Note, that `django-fobi` auto-discovers your plugins if you place
|
||||
them into a file named `fobi_form_elements.py` of any Django app listed in
|
||||
them into a file named ``fobi_form_elements.py`` of any Django app listed in
|
||||
``INSTALLED_APPS`` of your Django projects' settings module.
|
||||
|
||||
path/to/sample_textarea/fobi_form_elements.py
|
||||
|
|
@ -475,11 +476,11 @@ path/to/sample_textarea/forms.py
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Why to have another file for defining forms? Just to keep the code clean and
|
||||
less messy, although you could perfectly define all your plugin forms in the
|
||||
module `fobi_form_elements.py`, it's recommended to keep it separate.
|
||||
module ``fobi_form_elements.py``, it's recommended to keep it separate.
|
||||
|
||||
Take into consideration, that `forms.py` is not an auto-discovered file pattern.
|
||||
All your form element plugins should be registered in modules named
|
||||
`fobi_form_elements.py`.
|
||||
Take into consideration, that ``forms.py`` is not an auto-discovered file
|
||||
pattern. All your form element plugins should be registered in modules named
|
||||
``fobi_form_elements.py``.
|
||||
|
||||
Required imports.
|
||||
|
||||
|
|
@ -631,7 +632,7 @@ Do check the source code as example.
|
|||
|
||||
Define and register the form handler plugin
|
||||
-------------------------------------------
|
||||
Let's name that plugin `sample_mail`. The plugin directory should then have
|
||||
Let's name that plugin ``sample_mail``. The plugin directory should then have
|
||||
the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
|
@ -704,11 +705,11 @@ plugin is configurable, it should have a form.
|
|||
|
||||
Why to have another file for defining forms? Just to keep the code clean and
|
||||
less messy, although you could perfectly define all your plugin forms in the
|
||||
module `fobi_form_handlers.py`, it's recommended to keep it separate.
|
||||
module ``fobi_form_handlers.py``, it's recommended to keep it separate.
|
||||
|
||||
Take into consideration, that `forms.py` is not an auto-discovered file pattern.
|
||||
All your form handler plugins should be registered in modules named
|
||||
`fobi_form_handlers.py`.
|
||||
Take into consideration, that ``forms.py`` is not an auto-discovered file
|
||||
pattern. All your form handler plugins should be registered in modules named
|
||||
``fobi_form_handlers.py``.
|
||||
|
||||
Required imports.
|
||||
|
||||
|
|
@ -837,8 +838,8 @@ existing MailChimp forms into `django-fobi`.
|
|||
|
||||
Define and register the form importer plugin
|
||||
--------------------------------------------
|
||||
Let's name that plugin `sample_importer`. The plugin directory should then have
|
||||
the following structure.
|
||||
Let's name that plugin ``sample_importer``. The plugin directory should then
|
||||
have the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
|
@ -938,7 +939,7 @@ Required imports.
|
|||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from sample_service_api import sample_api # Just an imaginary API client
|
||||
from sample_service_api import sample_api # Just an imaginary API client
|
||||
|
||||
Defining the form for Sample importer plugin.
|
||||
|
||||
|
|
@ -988,7 +989,8 @@ Required imports.
|
|||
from formtools.wizard.views import SessionWizardView
|
||||
|
||||
from path.to.sample_importer.forms import (
|
||||
SampleImporterStep1Form, SampleImporterStep2Form
|
||||
SampleImporterStep1Form,
|
||||
SampleImporterStep2Form,
|
||||
)
|
||||
|
||||
Defining the wizard view for Sample importer plugin.
|
||||
|
|
@ -1076,9 +1078,8 @@ Creating a form callback
|
|||
Form callbacks are additional hooks, that are executed on various stages of
|
||||
the form submission.
|
||||
|
||||
Let's place the callback in the `foo` module. The plugin directory should then
|
||||
have the following
|
||||
structure.
|
||||
Let's place the callback in the ``foo`` module. The plugin directory should
|
||||
then have the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
|
@ -1162,7 +1163,7 @@ themes:
|
|||
- "Foundation 5" theme
|
||||
- "Simple" theme in (with editing interface in style of the Django admin)
|
||||
- "DjangoCMS admin style" theme (which is another simple theme with editing
|
||||
interface in style of `djangocms-admin-style`)
|
||||
interface in style of ``djangocms-admin-style``)
|
||||
|
||||
Obviously, there are two sorts of views when it comes to editing and viewing
|
||||
the form.
|
||||
|
|
@ -1192,7 +1193,7 @@ the "Simple" theme is the best start, since it looks just like django-admin.
|
|||
Create a new theme
|
||||
------------------
|
||||
|
||||
Let's place the theme in the `sample_theme` module. The theme directory
|
||||
Let's place the theme in the ``sample_theme`` module. The theme directory
|
||||
should then have the following structure.
|
||||
|
||||
.. code-block:: text
|
||||
|
|
@ -1292,7 +1293,7 @@ Registering the ``SampleTheme`` plugin.
|
|||
|
||||
Sometimes you would want to attach additional properties to the theme
|
||||
in order to use them later in templates (remember, current theme object
|
||||
is always available in templates under name `fobi_theme`).
|
||||
is always available in templates under name ``fobi_theme``).
|
||||
|
||||
For such cases you would need to define a variable in your project's settings
|
||||
module, called ``FOBI_CUSTOM_THEME_DATA``. See the following code as example:
|
||||
|
|
@ -1742,7 +1743,7 @@ The following HTML5 fields are supported in corresponding bundled plugins:
|
|||
- placeholder
|
||||
- type
|
||||
|
||||
With the `fobi.contrib.plugins.form_elements.fields.input` support for
|
||||
With the ``fobi.contrib.plugins.form_elements.fields.input`` support for
|
||||
HTML5 fields is extended to the following fields:
|
||||
|
||||
- autocomplete
|
||||
|
|
@ -1769,7 +1770,7 @@ Dynamic initial values
|
|||
It's possible to provide a dynamic initial value for any of the text elements.
|
||||
In order to do that, you should use the build-in context processor or make
|
||||
your own one. The only requirement is that you should store all values that
|
||||
should be exposes in the form as a dict for `fobi_dynamic_values` dictionary
|
||||
should be exposes in the form as a dict for ``fobi_dynamic_values`` dictionary
|
||||
key. Beware, that passing the original request object might be unsafe in
|
||||
many ways. Currently, a stripped down version of the request object is being
|
||||
passed as a context variable.
|
||||
|
|
@ -1793,7 +1794,8 @@ passed as a context variable.
|
|||
}
|
||||
}
|
||||
|
||||
In your GUI, you should be refering to the initial values in the following way:
|
||||
In your GUI, you should be referring to the initial values in the following
|
||||
way:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
|
|
@ -1807,21 +1809,21 @@ Currently, the following variables are available in the
|
|||
|
||||
- request: Stripped HttpRequest object.
|
||||
|
||||
- request.path: A string representing the full path to the requested page,
|
||||
not including the scheme or domain.
|
||||
- request.path: A string representing the full path to the requested
|
||||
page, not including the scheme or domain.
|
||||
|
||||
- request.get_full_path(): Returns the path, plus an appended query string,
|
||||
if applicable.
|
||||
- request.get_full_path(): Returns the path, plus an appended query
|
||||
string, if applicable.
|
||||
|
||||
- request.is_secure(): Returns True if the request is secure; that is, if
|
||||
it was made with HTTPS.
|
||||
- request.is_secure(): Returns True if the request is secure; that
|
||||
is, if it was made with HTTPS.
|
||||
|
||||
- request.is_ajax(): Returns True if the request was made via an
|
||||
XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the
|
||||
string 'XMLHttpRequest'.
|
||||
|
||||
- request.META: A stripped down standard Python dictionary containing the
|
||||
available HTTP headers.
|
||||
- request.META: A stripped down standard Python dictionary containing
|
||||
the available HTTP headers.
|
||||
|
||||
- HTTP_ACCEPT_ENCODING: Acceptable encodings for the response.
|
||||
|
||||
|
|
@ -1833,7 +1835,7 @@ Currently, the following variables are available in the
|
|||
|
||||
- HTTP_USER_AGENT: The client’s user-agent string.
|
||||
|
||||
- QUERY_STRING: The query string, as a single (unparsed) string.
|
||||
- QUERY_STRING: The query string, as a single (un-parsed) string.
|
||||
|
||||
- REMOTE_ADDR: The IP address of the client.
|
||||
|
||||
|
|
@ -1841,9 +1843,9 @@ Currently, the following variables are available in the
|
|||
|
||||
- request.user.email:
|
||||
|
||||
- request.user.get_username(): Returns the username for the user. Since
|
||||
the User model can be swapped out, you should use this method
|
||||
instead of referencing the username attribute directly.
|
||||
- request.user.get_username(): Returns the username for the user.
|
||||
Since the User model can be swapped out, you should use this
|
||||
method instead of referencing the username attribute directly.
|
||||
|
||||
- request.user.get_full_name(): Returns the first_name plus the
|
||||
last_name, with a space in between.
|
||||
|
|
@ -2038,10 +2040,11 @@ install the test requirements:
|
|||
|
||||
Browser tests
|
||||
-------------
|
||||
For browser tests you may choose between Firefox and PhantomJS. PhantomJS is
|
||||
faster, Firefox tests tell you more. Both cases require some effort and both
|
||||
have disadvantages regarding the installation (although once you have them
|
||||
installed they work perfect).
|
||||
For browser tests you may choose between Firefox, headless Firefox and
|
||||
PhantomJS. PhantomJS is faster, headless Firefox is fast as well, but
|
||||
normal Firefox tests tell you more (as you see what exactly happens on the
|
||||
screen). Both cases require some effort and both have disadvantages regarding
|
||||
the installation (although once you have them installed they work perfect).
|
||||
|
||||
Latest versions of Firefox are often not supported by Selenium. Current
|
||||
version of the Selenium for Python (2.53.6) works fine with Firefox 47.
|
||||
|
|
@ -2063,10 +2066,31 @@ Set up Firefox 47
|
|||
|
||||
FIREFOX_BIN_PATH = '/usr/lib/firefox47/firefox'
|
||||
|
||||
If you set ``FIREFOX_BIN_PATH`` to None, system Firefox would be used.
|
||||
If you set to use system Firefox, remove or comment-out the
|
||||
``FIREFOX_BIN_PATH`` setting.
|
||||
|
||||
After that your Selenium tests would work.
|
||||
|
||||
Set up headless Firefox
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
1. Install ``xvfb`` package which is used to start Firefox in headless mode.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
sudo apt-get install xvfb
|
||||
|
||||
2. Run the tests using headless Firefox.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./scripts/runtests.sh
|
||||
|
||||
Or run tox tests using headless Firefox.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./scripts/tox.sh
|
||||
|
||||
Setup PhantomJS
|
||||
~~~~~~~~~~~~~~~
|
||||
You could also run tests in headless mode (faster). For that you will need
|
||||
|
|
@ -2088,14 +2112,14 @@ PhantomJS.
|
|||
|
||||
PHANTOM_JS_EXECUTABLE_PATH = ""
|
||||
|
||||
If you want to use Firefox for testing, set
|
||||
``PHANTOM_JS_EXECUTABLE_PATH`` to None.
|
||||
If you want to use Firefox for testing, remove or comment-out the
|
||||
``PHANTOM_JS_EXECUTABLE_PATH`` setting.
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
If you get a ``FormElementPluginDoesNotExist`` or a
|
||||
``FormHandlerPluginDoesNotExist`` exception, make sure you have listed your
|
||||
plugin in the `settings` module of your project.
|
||||
plugin in the ``settings`` module of your project.
|
||||
|
||||
License
|
||||
=======
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ Installation and configuration
|
|||
------------------------------
|
||||
Install the package in your environment.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. code-block:: none
|
||||
.. code-block:: sh
|
||||
|
||||
pip install django-fobi
|
||||
|
||||
INSTALLED_APPS
|
||||
^^^^^^^^^^^^^^
|
||||
Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your
|
||||
`settings` module.
|
||||
``settings`` module.
|
||||
|
||||
1. The core.
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your
|
|||
<https://github.com/barseghyanartur/django-fobi/tree/stable/src/fobi/contrib/plugins/form_elements/security/recaptcha/>`_
|
||||
would require additional packages to be installed. If so, make sure to have
|
||||
installed and configured those dependencies prior adding the dependant
|
||||
add-ons to the `settings` module.
|
||||
add-ons to the ``settings`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
'easy_thumbnails', # Required by `content_image` plugin
|
||||
'easy_thumbnails', # Required by `content_image` plugin
|
||||
'fobi.contrib.plugins.form_elements.content.content_image',
|
||||
'fobi.contrib.plugins.form_elements.content.content_text',
|
||||
'fobi.contrib.plugins.form_elements.content.content_video',
|
||||
|
|
@ -145,7 +145,7 @@ Putting all together, you would have something like this.
|
|||
'fobi.contrib.plugins.form_elements.fields.url',
|
||||
|
||||
# Form element plugins
|
||||
'easy_thumbnails', # Required by `content_image` plugin
|
||||
'easy_thumbnails', # Required by ``content_image`` plugin
|
||||
'fobi.contrib.plugins.form_elements.content.content_image',
|
||||
'fobi.contrib.plugins.form_elements.content.content_text',
|
||||
'fobi.contrib.plugins.form_elements.content.content_video',
|
||||
|
|
@ -162,21 +162,21 @@ TEMPLATE_CONTEXT_PROCESSORS
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Add ``django.core.context_processors.request`` and
|
||||
``fobi.context_processors.theme`` to ``TEMPLATE_CONTEXT_PROCESSORS`` of
|
||||
your `settings` module.
|
||||
your ``settings`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
# ...
|
||||
"django.core.context_processors.request",
|
||||
"fobi.context_processors.theme", # Obligatory
|
||||
"fobi.context_processors.dynamic_values", # Optional
|
||||
"fobi.context_processors.theme", # Obligatory
|
||||
"fobi.context_processors.dynamic_values", # Optional
|
||||
# ...
|
||||
)
|
||||
|
||||
urlpatterns
|
||||
^^^^^^^^^^^
|
||||
Add the following line to ``urlpatterns`` of your `urls` module.
|
||||
Add the following line to ``urlpatterns`` of your ``urls`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
@ -201,21 +201,21 @@ Update the database
|
|||
1. First you should be syncing/migrating the database. Depending on your
|
||||
Django version and migration app, this step may vary. Typically as follows:
|
||||
|
||||
.. code-block:: none
|
||||
.. code-block:: sh
|
||||
|
||||
$ ./manage.py syncdb
|
||||
$ ./manage.py migrate --fake-initial
|
||||
./manage.py syncdb
|
||||
./manage.py migrate --fake-initial
|
||||
|
||||
2. Sync installed ``fobi`` plugins. Go to terminal and type the following
|
||||
command.
|
||||
|
||||
.. code-block:: none
|
||||
.. code-block:: sh
|
||||
|
||||
$ ./manage.py fobi_sync_plugins
|
||||
./manage.py fobi_sync_plugins
|
||||
|
||||
Specify the active theme
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Specify the default theme in your `settings` module.
|
||||
Specify the default theme in your ``settings`` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
|||
1
scripts/runtests.sh
Executable file
1
scripts/runtests.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
xvfb-run python runtests.py
|
||||
1
scripts/tox.sh
Executable file
1
scripts/tox.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
xvfb-run python toxtests.py
|
||||
4
setup.py
4
setup.py
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from distutils.version import LooseVersion
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
version = '0.10.6'
|
||||
version = '0.10.7'
|
||||
|
||||
# ***************************************************************************
|
||||
# ************************** Python version *********************************
|
||||
|
|
@ -78,7 +78,7 @@ except Exception as err:
|
|||
try:
|
||||
readme = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
|
||||
screenshots = open(
|
||||
os.path.join(os.path.dirname(__file__), 'SCREENSHOTS.rst')
|
||||
os.path.join(os.path.dirname(__file__), 'docs/screenshots.rst.distrib')
|
||||
).read()
|
||||
screenshots = screenshots.replace(
|
||||
'.. image:: _static',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
__title__ = 'django-fobi'
|
||||
__version__ = '0.10.6'
|
||||
__build__ = 0x000079
|
||||
__version__ = '0.10.7'
|
||||
__build__ = 0x00007a
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ def base_bulk_change_plugins(PluginForm, named_url, modeladmin, request,
|
|||
post = dict(request.POST)
|
||||
if selected:
|
||||
post['selected_plugins'] = ','.join(selected)
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = PluginForm(
|
||||
data=post,
|
||||
files=request.FILES,
|
||||
|
|
@ -455,7 +455,7 @@ class BasePluginModelAdmin(admin.ModelAdmin):
|
|||
This is where the data is actually processed.
|
||||
"""
|
||||
changelist_named_url = self._get_changelist_named_url()
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form_cls = self._get_bulk_change_form_class()
|
||||
form = form_cls(
|
||||
data=request.POST,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ import datetime
|
|||
|
||||
import simplejson as json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from nine.versions import DJANGO_GTE_1_10
|
||||
|
||||
from fobi.base import (
|
||||
# General
|
||||
get_processed_form_data,
|
||||
|
|
@ -24,6 +25,11 @@ from fobi.helpers import get_form_element_entries_for_form_wizard_entry
|
|||
from . import UID
|
||||
from .models import SavedFormDataEntry, SavedFormWizardDataEntry
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.db_store.fobi_form_handlers'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
import logging
|
||||
|
||||
import mailchimp
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import mailchimp
|
||||
|
||||
from fobi.wizard import SessionWizardView
|
||||
|
||||
from nine.versions import DJANGO_GTE_1_10
|
||||
|
||||
from .forms import MailchimpAPIKeyForm, MailchimpListIDForm
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_importers.mailchimp_importer.views'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
|
|||
|
|
@ -1,21 +1,28 @@
|
|||
from six import with_metaclass
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms.forms import BaseForm
|
||||
from django.forms.widgets import media_property
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
from nine.versions import DJANGO_GTE_1_7, DJANGO_GTE_1_8
|
||||
from nine.versions import (
|
||||
DJANGO_GTE_1_7,
|
||||
DJANGO_GTE_1_8,
|
||||
DJANGO_GTE_1_10,
|
||||
)
|
||||
|
||||
from six import with_metaclass
|
||||
|
||||
from .constants import WIZARD_TYPE_COOKIE, WIZARD_TYPE_SESSION
|
||||
|
||||
if DJANGO_GTE_1_8:
|
||||
from formtools.wizard.views import (
|
||||
WizardView, SessionWizardView, CookieWizardView
|
||||
CookieWizardView,
|
||||
SessionWizardView,
|
||||
WizardView,
|
||||
)
|
||||
else:
|
||||
from django.contrib.formtools.wizard.views import (
|
||||
WizardView, SessionWizardView, CookieWizardView
|
||||
CookieWizardView,
|
||||
SessionWizardView,
|
||||
WizardView,
|
||||
)
|
||||
|
||||
if DJANGO_GTE_1_7:
|
||||
|
|
@ -23,6 +30,11 @@ if DJANGO_GTE_1_7:
|
|||
else:
|
||||
from django.utils.datastructures import SortedDict as OrderedDict
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.dynamic'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
from six import text_type
|
||||
from nine.versions import DJANGO_GTE_1_10
|
||||
|
||||
import simplejson as json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from six import text_type
|
||||
|
||||
from .base import BaseRegistry
|
||||
from .discover import autodiscover
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.form_importers'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
|
|||
|
|
@ -3,47 +3,50 @@ Helpers module. This module can be safely imported from any fobi (sub)module,
|
|||
since it never imports from any of the fobi (sub)modules (except for the
|
||||
`fobi.constants` and `fobi.exceptions` modules).
|
||||
"""
|
||||
import os
|
||||
import glob
|
||||
import logging
|
||||
import uuid
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from six import text_type, PY3
|
||||
|
||||
import simplejson as json
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.files.base import File
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.utils import DatabaseError
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.html import format_html_join
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.test.client import RequestFactory
|
||||
from django.http import HttpResponse
|
||||
import uuid
|
||||
|
||||
from autoslug.settings import slugify
|
||||
|
||||
from nine.user import User
|
||||
from nine.versions import DJANGO_GTE_1_7
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
# from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.base import File
|
||||
# from django.db.utils import DatabaseError
|
||||
from django.http import HttpResponse
|
||||
from django.test.client import RequestFactory
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.html import format_html_join
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from fobi.constants import (
|
||||
SUBMIT_VALUE_AS_VAL,
|
||||
from nine.user import User
|
||||
from nine.versions import DJANGO_GTE_1_7, DJANGO_GTE_1_10
|
||||
|
||||
import simplejson as json
|
||||
|
||||
from six import text_type, PY3
|
||||
|
||||
from .constants import (
|
||||
SUBMIT_VALUE_AS_MIX,
|
||||
SUBMIT_VALUE_AS_REPR,
|
||||
SUBMIT_VALUE_AS_MIX
|
||||
SUBMIT_VALUE_AS_VAL,
|
||||
)
|
||||
from fobi.exceptions import ImproperlyConfigured
|
||||
from .exceptions import ImproperlyConfigured
|
||||
|
||||
if DJANGO_GTE_1_7:
|
||||
import django.apps
|
||||
|
||||
else:
|
||||
from django.db import models
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.helpers'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
@ -873,7 +876,7 @@ def get_wizard_form_field_value_from_request(request,
|
|||
return value
|
||||
|
||||
# Then try POST
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
value = get_wizard_form_field_value_from_post(
|
||||
request,
|
||||
wizard_view_name,
|
||||
|
|
@ -884,7 +887,7 @@ def get_wizard_form_field_value_from_request(request,
|
|||
|
||||
else:
|
||||
# First try POST
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
value = get_wizard_form_field_value_from_post(
|
||||
request,
|
||||
wizard_view_name,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from fobi.base import get_theme
|
||||
from ..base import get_theme
|
||||
|
||||
__title__ = 'fobi.integration.helpers'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
|
|
|
|||
|
|
@ -5,18 +5,22 @@ from django.template import RequestContext
|
|||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from fobi.base import (
|
||||
fire_form_callbacks, run_form_handlers,
|
||||
submit_plugin_form_data, get_theme
|
||||
from ..base import (
|
||||
fire_form_callbacks,
|
||||
get_theme,
|
||||
run_form_handlers,
|
||||
submit_plugin_form_data,
|
||||
)
|
||||
from fobi.constants import (
|
||||
CALLBACK_BEFORE_FORM_VALIDATION, CALLBACK_FORM_INVALID,
|
||||
CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA, CALLBACK_FORM_VALID,
|
||||
CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS
|
||||
from ..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.dynamic import assemble_form_class
|
||||
from fobi.exceptions import ImproperlyConfigured
|
||||
from fobi.settings import GET_PARAM_INITIAL_DATA
|
||||
from ..dynamic import assemble_form_class
|
||||
from ..exceptions import ImproperlyConfigured
|
||||
from ..settings import GET_PARAM_INITIAL_DATA
|
||||
|
||||
__title__ = 'fobi.integration.processors'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
|
|
@ -70,6 +74,7 @@ class IntegrationProcessor(object):
|
|||
)
|
||||
|
||||
def get_context_data(self, request, instance, **kwargs):
|
||||
"""Get context data."""
|
||||
context = {
|
||||
'form_entry': instance.form_entry,
|
||||
}
|
||||
|
|
@ -77,12 +82,15 @@ class IntegrationProcessor(object):
|
|||
return context
|
||||
|
||||
def get_form_template_name(self, request, instance):
|
||||
"""Get form template name."""
|
||||
return instance.form_template_name or None
|
||||
|
||||
def get_success_page_template_name(self, request, instance):
|
||||
"""Get succes page template name."""
|
||||
return instance.success_page_template_name or None
|
||||
|
||||
def get_login_required_template_name(self, request, instance):
|
||||
"""Get login required template name."""
|
||||
return self.login_required_template_name or None
|
||||
|
||||
def _process_form(self, request, instance, **kwargs):
|
||||
|
|
@ -121,7 +129,7 @@ class IntegrationProcessor(object):
|
|||
request=request
|
||||
)
|
||||
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = FormClass(request.POST, request.FILES)
|
||||
|
||||
# Fire pre form validation callbacks
|
||||
|
|
@ -133,8 +141,7 @@ class IntegrationProcessor(object):
|
|||
)
|
||||
|
||||
if form.is_valid():
|
||||
# Fire form valid callbacks, before handling sufrom
|
||||
# django.http import HttpResponseRedirectbmitted plugin
|
||||
# Fire form valid callbacks, before handling submitted plugin
|
||||
# form data
|
||||
form = fire_form_callbacks(
|
||||
form_entry=instance.form_entry,
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ from __future__ import absolute_import
|
|||
|
||||
import logging
|
||||
|
||||
from autoslug import AutoSlugField
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from autoslug import AutoSlugField
|
||||
from nine.versions import DJANGO_GTE_1_10
|
||||
|
||||
from six import python_2_unicode_compatible
|
||||
|
||||
|
|
@ -18,10 +19,15 @@ from .base import (
|
|||
form_wizard_handler_plugin_registry,
|
||||
get_registered_form_element_plugins,
|
||||
get_registered_form_handler_plugins,
|
||||
get_registered_form_wizard_handler_plugins
|
||||
get_registered_form_wizard_handler_plugins,
|
||||
)
|
||||
from .constants import WIZARD_TYPES, DEFAULT_WIZARD_TYPE
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.models'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ __all__ = (
|
|||
|
||||
THEME = get_theme(request=None, as_instance=True)
|
||||
|
||||
REGISTER = Library()
|
||||
register = Library()
|
||||
|
||||
# *****************************************************************************
|
||||
# *****************************************************************************
|
||||
|
|
@ -63,7 +63,7 @@ class GetFobiPluginNode(Node):
|
|||
return ''
|
||||
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def get_fobi_plugin(parser, token):
|
||||
"""Get the plugin.
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ class GetFobiFormHandlerPluginCustomActionsNode(Node):
|
|||
return ''
|
||||
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def get_fobi_form_handler_plugin_custom_actions(parser, token):
|
||||
"""Get the form handler plugin custom actions.
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ class GetFobiFormWizardHandlerPluginCustomActionsNode(Node):
|
|||
return ''
|
||||
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def get_fobi_form_wizard_handler_plugin_custom_actions(parser, token):
|
||||
"""Get the form wizard handler plugin custom actions.
|
||||
|
||||
|
|
@ -275,12 +275,12 @@ def render_auth_link(context):
|
|||
}
|
||||
|
||||
|
||||
REGISTER.inclusion_tag(
|
||||
register.inclusion_tag(
|
||||
'fobi/snippets/render_auth_link.html', takes_context=True
|
||||
)(render_auth_link)
|
||||
|
||||
|
||||
@REGISTER.inclusion_tag(THEME.forms_list_template, takes_context=True)
|
||||
@register.inclusion_tag(THEME.forms_list_template, takes_context=True)
|
||||
def render_fobi_forms_list(context, queryset, *args, **kwargs):
|
||||
"""Render the list of fobi forms.
|
||||
|
||||
|
|
@ -366,7 +366,7 @@ class HasEditFormEntryPermissionsNode(Node):
|
|||
return False
|
||||
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def has_edit_form_entry_permissions(parser, token):
|
||||
"""Checks the permissions
|
||||
|
||||
|
|
@ -456,7 +456,7 @@ class GetFormFieldTypeNode(Node):
|
|||
return ''
|
||||
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def get_form_field_type(parser, token):
|
||||
"""Get form field type.
|
||||
|
||||
|
|
@ -515,7 +515,7 @@ class GetFormHiddenFieldsErrorsNode(Node):
|
|||
return ''
|
||||
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def get_form_hidden_fields_errors(parser, token):
|
||||
"""Get form hidden fields errors.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ except ImportError:
|
|||
from django.utils.safestring import mark_safe, EscapeData, SafeData
|
||||
from django.utils.timezone import template_localtime
|
||||
|
||||
REGISTER = Library()
|
||||
register = Library()
|
||||
|
||||
def render_value_in_context(value, context):
|
||||
"""Render value in context.
|
||||
|
|
@ -56,7 +56,7 @@ except ImportError:
|
|||
return render_value_in_context(value, context)
|
||||
return ''
|
||||
|
||||
@REGISTER.tag
|
||||
@register.tag
|
||||
def firstof(parser, token, escape=False):
|
||||
"""Outputs the first variable passed that is not False.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,13 @@ from selenium.webdriver.support.wait import WebDriverWait
|
|||
from selenium.common.exceptions import WebDriverException
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import LiveServerTestCase
|
||||
from django.conf import settings
|
||||
|
||||
from fobi.models import FormEntry
|
||||
|
||||
from nine.versions import DJANGO_GTE_1_10
|
||||
|
||||
from . import constants
|
||||
from .base import print_info, skip
|
||||
from .data import (
|
||||
|
|
@ -31,6 +32,10 @@ from .helpers import (
|
|||
phantom_js_clean_up
|
||||
)
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.tests.test_browser_build_dynamic_forms'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@ Another helper module. This module can NOT be safely imported from any fobi
|
|||
(sub)module - thus should be imported carefully.
|
||||
"""
|
||||
import datetime
|
||||
import os
|
||||
import logging
|
||||
|
||||
from six import PY3
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms.widgets import TextInput
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from nine.versions import DJANGO_GTE_1_10
|
||||
|
||||
from six import PY3
|
||||
|
||||
from .base import (
|
||||
form_element_plugin_registry,
|
||||
form_handler_plugin_registry,
|
||||
|
|
@ -42,6 +43,11 @@ from .models import (
|
|||
)
|
||||
from .settings import RESTRICT_PLUGIN_ACCESS, DEBUG, WIZARD_FILES_UPLOAD_DIR
|
||||
|
||||
if DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
__title__ = 'fobi.utils'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2017 Artur Barseghyan'
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ from django.contrib import messages
|
|||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms import ValidationError
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import redirect
|
||||
|
|
@ -87,7 +86,9 @@ from .wizard import DynamicSessionWizardView, DynamicCookieWizardView
|
|||
|
||||
if versions.DJANGO_GTE_1_10:
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import render_to_response
|
||||
|
||||
if versions.DJANGO_GTE_1_8:
|
||||
|
|
@ -352,7 +353,7 @@ def create_form_entry(request, theme=None, template_name=None):
|
|||
:param str template_name:
|
||||
:return django.http.HttpResponse:
|
||||
"""
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = FormEntryForm(request.POST, request.FILES, request=request)
|
||||
if form.is_valid():
|
||||
form_entry = form.save(commit=False)
|
||||
|
|
@ -429,7 +430,7 @@ def edit_form_entry(request, form_entry_id, theme=None, template_name=None):
|
|||
except ObjectDoesNotExist as err:
|
||||
raise Http404(ugettext("Form entry not found."))
|
||||
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
# The form entry form (does not contain form elements)
|
||||
form = FormEntryForm(request.POST, request.FILES, instance=form_entry,
|
||||
request=request)
|
||||
|
|
@ -672,7 +673,7 @@ def add_form_element_entry(request,
|
|||
save_object = True
|
||||
|
||||
# If POST
|
||||
elif 'POST' == request.method:
|
||||
elif request.method == 'POST':
|
||||
# If element has a form
|
||||
form = form_element_plugin.get_initialised_create_form_or_404(
|
||||
data=request.POST,
|
||||
|
|
@ -759,7 +760,7 @@ def edit_form_element_entry(request,
|
|||
|
||||
:param django.http.HttpRequest request:
|
||||
:param int form_element_entry_id:
|
||||
:param fobi.base.BaseTheme: Theme instance.
|
||||
:param fobi.base.BaseTheme theme: Theme instance.
|
||||
:param string template_name:
|
||||
:return django.http.HttpResponse:
|
||||
"""
|
||||
|
|
@ -787,7 +788,7 @@ def edit_form_element_entry(request,
|
|||
)
|
||||
return redirect('fobi.edit_form_entry', form_entry_id=form_entry.pk)
|
||||
|
||||
elif 'POST' == request.method:
|
||||
elif request.method == 'POST':
|
||||
form = form_element_plugin.get_initialised_edit_form_or_404(
|
||||
data=request.POST,
|
||||
files=request.FILES
|
||||
|
|
@ -942,7 +943,7 @@ def add_form_handler_entry(request,
|
|||
if not form_handler_plugin_form_cls:
|
||||
save_object = True
|
||||
|
||||
elif 'POST' == request.method:
|
||||
elif request.method == 'POST':
|
||||
form = form_handler_plugin.get_initialised_create_form_or_404(
|
||||
data=request.POST,
|
||||
files=request.FILES
|
||||
|
|
@ -1042,7 +1043,7 @@ def edit_form_handler_entry(request,
|
|||
)
|
||||
return redirect('fobi.edit_form_entry', form_entry_id=form_entry.pk)
|
||||
|
||||
elif 'POST' == request.method:
|
||||
elif request.method == 'POST':
|
||||
form = form_handler_plugin.get_initialised_edit_form_or_404(
|
||||
data=request.POST,
|
||||
files=request.FILES
|
||||
|
|
@ -1146,7 +1147,7 @@ def create_form_wizard_entry(request, theme=None, template_name=None):
|
|||
:param str template_name:
|
||||
:return django.http.HttpResponse:
|
||||
"""
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = FormWizardEntryForm(request.POST,
|
||||
request.FILES,
|
||||
request=request)
|
||||
|
|
@ -1231,7 +1232,7 @@ def edit_form_wizard_entry(request, form_wizard_entry_id, theme=None,
|
|||
except ObjectDoesNotExist as err:
|
||||
raise Http404(ugettext("Form wizard entry not found."))
|
||||
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
# The form entry form (does not contain form elements)
|
||||
form = FormWizardEntryForm(request.POST, request.FILES,
|
||||
instance=form_wizard_entry,
|
||||
|
|
@ -1952,7 +1953,7 @@ def add_form_wizard_handler_entry(request,
|
|||
if not form_wizard_handler_plugin_form_cls:
|
||||
save_object = True
|
||||
|
||||
elif 'POST' == request.method:
|
||||
elif request.method == 'POST':
|
||||
form = form_wizard_handler_plugin.get_initialised_create_form_or_404(
|
||||
data=request.POST,
|
||||
files=request.FILES
|
||||
|
|
@ -2059,7 +2060,7 @@ def edit_form_wizard_handler_entry(request,
|
|||
form_wizard_entry_id=form_wizard_entry.pk
|
||||
)
|
||||
|
||||
elif 'POST' == request.method:
|
||||
elif request.method == 'POST':
|
||||
form = form_wizard_handler_plugin.get_initialised_edit_form_or_404(
|
||||
data=request.POST,
|
||||
files=request.FILES
|
||||
|
|
@ -2176,7 +2177,7 @@ def view_form_entry(request, form_entry_slug, theme=None, template_name=None):
|
|||
request=request
|
||||
)
|
||||
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = form_cls(request.POST, request.FILES)
|
||||
|
||||
# Fire pre form validation callbacks
|
||||
|
|
@ -2405,7 +2406,7 @@ def import_form_entry(request, template_name=None):
|
|||
:param string template_name:
|
||||
:return django.http.HttpResponse:
|
||||
"""
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = ImportFormEntryForm(request.POST, request.FILES)
|
||||
|
||||
if form.is_valid():
|
||||
|
|
@ -2610,7 +2611,7 @@ def import_form_wizard_entry(request, template_name=None):
|
|||
:param string template_name:
|
||||
:return django.http.HttpResponse:
|
||||
"""
|
||||
if 'POST' == request.method:
|
||||
if request.method == 'POST':
|
||||
form = ImportFormWizardEntryForm(request.POST, request.FILES)
|
||||
|
||||
if form.is_valid():
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import re
|
|||
|
||||
from django import forms
|
||||
from django.shortcuts import redirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms import formsets, ValidationError
|
||||
from django.views.generic import TemplateView
|
||||
from django.utils.decorators import classonlymethod
|
||||
|
|
@ -24,6 +23,11 @@ else:
|
|||
)
|
||||
from django.contrib.formtools.wizard.forms import ManagementForm
|
||||
|
||||
if versions.DJANGO_GTE_1_10:
|
||||
from django.urls import reverse
|
||||
else:
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = (
|
||||
|
|
|
|||
5
toxtests.py
Normal file
5
toxtests.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from tox.session import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in a new issue