Welcome to django-dynamic-forms’s documentation!¶
Contents:
Installation¶
Install django-dynamic-forms into your virtual environment or you site-packages using pip:
$ pip install django-dynamic-forms
If you already use the wheel package format you can use the wheel build:
$ pip install --use-wheel django-dynamic-forms
To make django-dynamic-forms available in your Django project, you first have to add it to the INSTALLED_APPS in your settings.py. If you are unsure where to put it, just append it:
INSTALLED_APPS = (
...
'dynamic_forms',
...
)
To make Django aware of the dynamic forms while processing the requests / responses you need to add the FormModelMiddleware to the list of MIDDLEWARE_CLASSES. The best place is probably at the end of the list. If your forms are not shown please refer to the known problems section of the documentation:
MIDDLEWARE_CLASSES = (
...
'dynamic_forms.middlewares.FormModelMiddleware'
)
Last but not least you need to add the 'dynamic_forms.urls' urlpatterns to your project’s URL patterns:
urlpatterns = patterns('',
...
url(r'^dynamic_forms/',
include('dynamic_forms.urls', namespace='dynamic_forms')),
...
)
Important
Make sure that you get the namespace straight: dynamic_forms!
Finally you have to update your database. If you use Django>=1.7 you need to run:
$ python manage.py migrate dynamic_forms
If you use South you need to run:
$ python manage.py syncdb
$ python manage.py migrate
otherwise, if you don’t use South or if you use Django<1.7, you have to run:
$ python manage.py syncdb
Usage¶
Using Custom Templates¶
django-dynamic-forms comes with a basic template that just displays the form or a success page. You can customize these templates to your needs.
The Form Template¶
The following code shows the default template rendering a dynamic form.
{% load i18n %}
<h2>{{ name }}</h2>
<form method="post" action="{{ submit_url }}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">{% trans "Submit" %}</button>
</form>
The DynamicFormView exposes three variables to the template context related to the form:
- form
- An instance of the form that will be shown on this page. As the form is a normal Django form, all rules from the Django documentation apply.
- model
- An instance of the form model providing the form and assigned to this URL.
- name
- The form’s name as defined in dynamic_forms.models.FormModel.name.
- success_url
- The URL the form will be submitted to as defined in dynamic_forms.models.FormModel.submit_url. This is not the success_url!
The Success Template¶
The following code shows the success template after a successful form submit.
{% load i18n %}
<h2>{% trans "Success" %}</h2>
<p>{% trans "Form submitted successfully" %}</p>
{% if data %}<p>{% blocktrans with link=data.show_url_link %}For your convenience you can see your data at {{ link }}.{% endblocktrans %}</p>{% endif %}
The DynamicTemplateView exposes two variables to the template context related to the form:
- model
- An instance of the form model assigned to this URL.
- data
- If an instance of FormModelData if a existing display_key is given and the form model (model) has set allow_display to True.
Third Party Apps¶
django-simple-captcha¶
django-simple-captcha provides easy CAPTCHA support for Django forms. This contrib package integrates django-simple-captcha into django-dynamic-forms allowing users to add a CAPTCHA field to their dynamic forms.
To use it make sure you installed django-simple-captcha:
$ pip install django-simple-captcha
Next put 'captcha' and 'dynamic_forms.contrib.simple_captcha' in the INSTALLED_APPS:
INSTALLED_APPS = (
...
'captcha',
'dynamic_forms.contrib.simple_captcha',
...
)
Problems¶
My form is not shown¶
If you are sure you followed the Installation instructions, there are several reasons:
- You might have misspelled the URL path. Please check again.
- There is another view that maps to the URL you defined in your model. 1. If you have Django’s flatpages framework installed, check please check that there is not page mapping to this URL.
- An error occurs while constructing the form or rendering the template. Set DEBUG = True in your settings.py and have a look at the exception that is raised.
Changes¶
v0.3.4¶
- Fixed a issue with missing migrations on Python 2. (#11)
v0.3.3¶
- Updated Portuguese translation (thanks Gladson Simplicio) (#8)
v0.3.2¶
- Introduced the settings variables DYNAMIC_FORMS_FORM_TEMPLATES and DYNAMIC_FORMS_SUCCESS_TEMPLATES to make defining the templates for the form and success display easier and more usable for non-developers. (#1)
- Allow delayed registration of actions and dynamic form fields.
- Allow dynamic fields to exclude their value from the mapped_data by overriding do_display_data().
- Support for django-simple-captcha (#2)
- Add Portuguese translation (thanks Gladson Simplicio) (#4)
- Replaced formfields.dynamic_form_field_registry with formfields.formfield_registry and deprecated the former.
- Fixed sorting of actions and field types by their label (#5)
- Allow users to get a link to see the data they submitted before at a later time (#6)
v0.2¶
- Fixed some packaging issues (thanks Jannis Leidel)
- Add Django 1.7’s db.migrations
- Moved to tox for development testing
v0.1¶
- Initital release
References¶
Actions¶
Actions define what happens once a user submits a FormModelForm. django-dynamic-forms provides two basic actions dynamic_form_send_email() and dynamic_form_store_database() that, as their names indicate, either send the submitted data via e-mail to the receipients defined in the DYNAMIC_FORMS_EMAIL_RECIPIENTS settings variable or stores it into the database (precisely the FormModelData model).
Any action that should be available for usage must be registered in the ActionRegistry. This can be done with the following code:
>>> def my_function(form_model, form):
... # do something
... pass
...
>>> from dynamic_forms.actions import action_registry
>>> action_registry.register(my_function, 'My Label')
This allows one to register an action during runtime. But many actions are already available during compile or start-up time and can be registered then by using a handy decorator formmodel_action(). Given the above situation, this would look like:
>>> from dynamic_forms.actions import formmodel_action
>>> @formmodel_action('My Label')
... def my_function(form_model, form):
... # do something
... pass
...
New in version 0.3: When a dynamic form is submitted through DynamicFormView the return values of actions are kept for further usage. This allows the view to e.g. add a link to a permanent URL refering to some stored values.
Providing and accessing actions¶
ActionRegistry¶
- class dynamic_forms.actions.ActionRegistry¶
The ActionRegistry keeps track of all available actions available to the software. It is available to the outside through the action_registry singleton
Warning
You should not import the ActionRegistry directly! Always use the singleton instance action_registry!
>>> from dynamic_forms.actions import action_registry
- get(key)¶
Parameters: key (str) – The key to get an action Returns: Either the action previously registered or None if no action with the given key has been found.
- get_as_choices()¶
Changed in version 0.3: Returns a generator instead of a list
Returns a generator that yields all registered actions as 2-tuples in the form (key, label).
- register(func, label)¶
Registers the function func with the label label. The function will internally be referred by it’s full qualified name:
'%s.%s' % (func.__module__, func.__name__)
Parameters:
- dynamic_forms.actions.action_registry¶
The singleton instance of the ActionRegistry.
Action registry utilities¶
- @dynamic_forms.actions.formmodel_action(label)¶
Registering various actions by hand can be time consuming. This function decorator eases this heavily: given a string as the first argument, this decorator registeres the decorated function withing the action_registry with its fully dotted Python path.
Usage:
@formmodel_action('My super awesome action') def my_action(form_model, form): # do something with the data ...
This is equivalent to:
def my_action(form_model, form): # do something with the data ... action_registry.register(my_action, 'My super awesome action')
Default Actions¶
- dynamic_forms.actions.dynamic_form_send_email(form_model, form)¶
Sends the data submitted through the form form via e-mail to all recipients listed in DYNAMIC_FORMS_EMAIL_RECIPIENTS.
Parameters: - form_model (dynamic_forms.models.FormModel) – The instance of the model defining the form.
- form (dynamic_forms.forms.FormModelForm) – The instance of the submitted form. One can get the data either using form.cleaned_data or, if the labels defined in the form_model for each field are needed, in the appropriate order by calling get_mapped_data().
- dynamic_forms.actions.dynamic_form_store_database(form_model, form)¶
This action takes the mapped data from the form and serializes it as JSON. This value is then stored in the FormModelData.
See also
dynamic_form_store_database() for a detailed explaination of the arguments.
New in version 0.3: To allow linking to a stored data set, the action now returns the inserted object.
Admin¶
Fields¶
- class dynamic_forms.fields.TextMultiSelectField([separate_values_by='\n', **options])¶
Provides multiple choice field storage for strings without limiting the total length of the string or giving any restrictions of which characters are not allowed because they are used to split the input value into its different choices.
Parameters: separate_values_by (str) – The string used to split the input value into its choices. Defaults to '\n'. See also
The respective form field as part of django-dynamic-forms dynamic_forms.forms.MultiSelectFormField. The common field options and the specifics for the django.db.models.TextField.
Note
The implementation is based on http://djangosnippets.org/snippets/2753/ but has been modified to the needs of this project. Thus, there is no conversion of the selected items to int or similar.
Form fields¶
- dynamic_forms.formfields.format_display_type(cls_name)¶
- dynamic_forms.formfields.load_class_from_string(cls_string)¶
DynamicFormFieldRegistry¶
- class dynamic_forms.formfields.DynamicFormFieldRegistry(object)¶
- get(key)¶
- get_as_choices()¶
Changed in version 0.3: Returns a generator instead of a list
Returns a generator that yields all registered dynamic form fields as 2-tuples in the form (key, display_type).
- register(cls)¶
- unregister(key)¶
- dynamic_forms.formfields.formfield_registry¶
New in version 0.3: Use this instead of dynamic_form_field_registry
- dynamic_forms.formfields.dynamic_form_field_registry¶
Deprecated since version 0.3: Deprecated in favor of formfield_registry
- @dynamic_forms.formfields.dynamic_form_field(cls)¶
A class decorator to register the class as a dynamic form field in the DynamicFormFieldRegistry.
Base Form Field Classes¶
DFFMetaclass¶
- class dynamic_forms.formfields.DFFMetaclass¶
Metaclass that inspects the Meta class of a class inheriting from BaseDynamicFormField and merges the different attributes that are later being passed to the respective django.forms.Field.
You are free to add an attribute _exclude of type list or tuple to the Meta class of a field to exclude any attributes inherited from a super DynamicFormField. Look at the implementation of the BooleanField for an example.
BaseDynamicFormField¶
- class dynamic_forms.formfields.BaseDynamicFormField¶
- cls¶
None
- display_type¶
None
- widget¶
None
- options¶
- class Meta¶
- help_text¶
[six.string_types, ‘’, (forms.CharField, forms.Textarea)]
- required¶
[bool, True, forms.NullBooleanField]
- dynamic_forms.formfields.__init__(name, label, widget_attrs={}, **kwargs)¶
- dynamic_forms.formfields.construct([**kwargs])¶
- dynamic_forms.formfields.contribute_to_form(form)¶
- dynamic_forms.formfields.get_display_type()¶
Returns a class’s display_type is defined or calls format_display_type() with the class’s name.
This function is only available to the class itself. It is not callable from an instance.
- dynamic_forms.formfields.get_widget_attrs()¶
- dynamic_forms.formfields.set_options([**kwargs])¶
- dynamic_forms.formfields.options_valid()¶
- classmethod dynamic_forms.formfields.do_display_data()¶
Default: True
Default Fields¶
- class dynamic_forms.formfields.ChoiceField¶
- cls¶
'django.forms.ChoiceField
- display_type¶
'Choices
- dynamic_forms.formfields.construct([**kwargs])
- dynamic_forms.formfields.options_valid()
- class dynamic_forms.formfields.DateTimeField¶
- cls¶
'django.forms.DateTimeField
- display_type¶
‘Date and Time’
- class dynamic_forms.formfields.MultiLineTextField¶
- cls¶
'django.forms.CharField
- display_type¶
'Multi Line Text
- widget¶
'django.forms.widgets.Textarea
Forms¶
Form Fields¶
- class dynamic_forms.forms.MultiSelectFormField([separate_values_by='\n', **options])¶
Provides multiple choice field storage for string objects without limiting the total length of the string.
Parameters: separate_values_by (str) – The string used to split the input value into its choices. Defaults to '\n'. See also
The respective database field as part of django-dynamic-forms dynamic_forms.fields.TextMultiSelectField. The core form field arguments and the specifics for the django.forms.MultipleChoiceField.
Note
The implementation is based on http://djangosnippets.org/snippets/2753/ but has been modified to the needs of this project.
Forms¶
- class dynamic_forms.forms.FormModelForm(model[, *args, **kwargs])¶
- get_mapped_data([exclude_missing=False])¶
Returns an dictionary sorted by the position of the respective field in its form.
Parameters: exclude_missing (boolean) – If True, non-filled fields (those whose value evaluates to False) are not present in the returned dictionary. Default: False
Middlewares¶
- class dynamic_forms.middlewares.FormModelMiddleware¶
This middleware intercepts all HTTP 404 responses and checks if there is a form mapped to this URL. This way an explicit URL mapping from the projects ROOT_URLCONF cannot accidentally be overridden by wrong setting for submit_url or success_url on dynamic_forms.models.FormModel.
This technique is comparable to the one used by Django’s FlatpageFallbackMiddleware.
- process_response(request, response)¶
The algorithm that decides if and which form to display works like this:
If the status_code for response is not 404 (NOT FOUND) this the FormModelMiddleware will return the response as-is and will not modify it. Thus, server error (5xx) will also not be affected by the middleware.
If there is a FormModel whose submit_url matches the request’s path_info, this model is used to construct and render the view.
If there is a FormModel whose success_url matches the request’s path_info, this model is used to display the success page.
Note
Since the success_url of a FormModel is not necessarily be unique, the first model that matches the request path will be used.
If any errors occur while processing a form the original request is returned (if DEBUG = True the respective exception is raised).
Models¶
FormModel¶
- class dynamic_forms.models.FormModel¶
- name¶
-
- max_length = 50
- unique = True
- submit_url¶
-
- max_length = 100
- unique = True
- success_url¶
-
- max_length = 100
- blank = True
- default = ''
- actions¶
dynamic_forms.fields.TextMultiSelectField
- default = ''
- choices = dynamic_forms.actions.ActionRegistry.get_as_choices()
- form_template¶
-
- max_length = 100
- choices = dynamic_forms.conf.DYNAMIC_FORMS_FORM_TEMPLATES
- success_template¶
-
- max_length = 100
- choices = dynamic_forms.conf.DYNAMIC_FORMS_SUCCESS_TEMPLATES
- allow_display¶
-
- default = False
- fields¶
Related name by FormFieldModel
- data¶
Related name by FormModelData
- dynamic_forms.models.get_fields_as_dict()¶
- dynamic_forms.models.save([*args, **kwargs])¶
FormFieldModel¶
- class dynamic_forms.models.FormFieldModel¶
-
- field_type¶
-
- max_length = 255
- choices = dynamic_forms.formfields.DynamicFormFieldRegistry.get_as_choices()
- label¶
-
- max_length = 20
- name¶
-
- max_length = 50
- blank = True
- _options¶
-
- blank = True
- null = True
- position¶
django.db.models.SmallIntegerField
- blank = True
- default = 0
- dynamic_forms.models.__str__()
- dynamic_forms.models.__unicode__()
- dynamic_forms.models.generate_form_field(form)¶
- dynamic_forms.models.get_form_field_kwargs()¶
- dynamic_forms.models.save([*args, **kwargs])
FormModelData¶
- class dynamic_forms.models.FormModelData¶
-
- value¶
-
- blank = True
- default = ''
- submitted¶
django.db.models.DateTimeField
- auto_now_add = True
- pretty_value()¶
- show_url¶
If the form this data set belongs to has allow_display == True, return the permanent URL. If displaying is not allowed, return an empty string.
Settings¶
DYNAMIC_FORMS_EMAIL_RECIPIENTS¶
- dynamic_forms.conf.DYNAMIC_FORMS_EMAIL_RECIPIENTS¶
A list of email addresses. Used to define the receipients form data will be send to if the action dynamic_form_send_email() is activated.
Defaults to all email addresses defined in the ADMINS setting.
DYNAMIC_FORMS_SUCCESS_TEMPLATES¶
- dynamic_forms.conf.DYNAMIC_FORMS_SUCCESS_TEMPLATES¶
New in version 0.3.
A tuple of 2-tuples passed to the FormModel‘s success_template attribute. This setting provides easier and less error-prone definition of the form template.
( ('dynamic_forms/form_success.html', _('Default success template')), )
Views¶
- class dynamic_forms.views.DynamicFormView¶
- form_valid(form)¶
Instantiates an empty dict self.action_results that takes the return values of every action that is called, unless the return value of that action is None.
- get_success_url()¶
If the dynamic_form_store_database action is active for the current form, include the display_key for the newly created data set.
- class dynamic_forms.views.DynamicTemplateView¶
- get_context_data(**kwargs)¶
If a display_key query parameter is given and the key belongs to a FormModel that has allow_display=True, add the data to the normal Django TemplateView context.