Open source feedback management system based on the Django framework. You can easily and flexibly embed any feedback form for your site. When the form is submitted you receive an email message containing the form data
- Easy installation and high level of customization.
- Works through AJAX (without page refresh)
- Flexible configuration of e-mail recipients and email message format.
- Built-in anti-spam protection and easy integration with any additional protection.
- Webpack/gulp compatible.
- Django 2.2.*
- Python 3.5
-
Install package
pip install git+git://github.com/shoker174/django-simple-feedback.git
-
Create (or use) your own application for your feedback forms, for example
custom_feedback
-
Configure your setting file:
- FEEDBACK_FORMS - Registry for feedback forms (required).
- FEEDBACK_FORMS_NAMES - Registry for feedback form names (required).
- FEEDBACK_PREFIX_KEY_FIELDS - Use True if need unique id html element for form fields. Recommended when more than one form (default: False).
- FEEDBACK_ANTISPAM - dictionary antispam settings. Include next settings:
- CHECKING_HIDDEN_FIELD - adding and checking hidden antispam fields in the form (default: True)
- BLOCKING_EXTERNAL_LINKS - checking form content for external links (default: True)
- FEEDBACK_ADMIN_EXTRA_CLASS - Admin page customizing: dictionary of extra css classes for fields (default empty). For example:
FEEDBACK_ADMIN_EXTRA_CLASS = {'all': 'my-class'}
- FEEDBACK_ADMIN_EXTRA_CSS - Admin page customizing: dictionary of extra css files for mailing list admin page (default empty). For example:
FEEDBACK_ADMIN_EXTRA_CSS = {'all': ['css/admin/common.css']}
Simple settings configuration:
# django email settings if they does not exist DEFAULT_FROM_EMAIL = '[email protected]' MANAGERS = [ ('websupport', '[email protected]'), ] EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # for local testing # feedback settings INSTALLED_APPS += ['feedback', '<PROJECT_ROOT>.custom_feedback'] FEEDBACK_FORMS = { 'my_form': '<PROJECT_ROOT>.custom_feedback.forms.MyForm', } FEEDBACK_FORMS_NAMES = { 'default': '-- default --', 'my_form': 'My form name', } FEEDBACK_PREFIX_KEY_FIELDS = True
-
Add urlpattern to main urls.py:
urlpatterns = [ ... url(r'^feedback/', include('feedback.urls')), ... ]
-
Create your custom form in directory according to FEEDBACK_FORMS settings. For example in dir
<PROJECT_ROOT>.custom_feedback.forms
from feedback.forms import BaseFeedbackForm class CallForm(BaseFeedbackForm): name = forms.CharField() email = forms.EmailField() phone = forms.CharField()
-
Call the form in the html template according FEEDBACK_FORMS settings
{% load feedback_tags %} ... <!--noindex--> {% show_feedback 'my_form' %} <!--/noindex-->
Any feedback form include three states (and accordingly three templates):
- presentation of form (feedback.html)
- message after success form sending (thankyou.html)
- message displayed when spam is blocked (spam.html)
-
Apply migrations and run local server
python manage.py migrate feedback python manage.py runserver
-
Create and configure recipients email adresses and mailing list for your custom form in admin.
Pay attention to the next mailing list fields:
- Form title - text displayed in form templates as form title.
- List of addresses - customize email recipients list instead of MANAGERS settings.
- Default sender email - customize email sender instead of DEFAULT_FROM_EMAIL settings.
- Success message - text displayed after success form sending.
- Message subject - topic for email message.
- Message template - email message template. All fields of the form are available in the field as variables in brackets. For example:
Name: {{ name }} E-mail: {{ email }} Phone: {{ phone }}
Configure is done!
To customize any feedback template, stick to the following template structure:
- templates/
- feedback/
- my_form/
- feedback.html
- feedback.html
- thankyou.html
- spam.html
- field.html
- my_form/
- feedback/
For example, when the "my_form" is rendered, the following priority applies:
- <PROJECT_ROOT>/templates/feedback/my_form/feedback.html
- <PROJECT_ROOT>/templates/feedback/feedback.html
- feedback/templates/feedback/feedback.html # default template from app
The following structure is most userfull:
- templates/
- feedback/
- my_form_1/
- feedback.html # customized form template
- my_form_2/
- feedback.html
- thankyou.html # common templates for all forms
- spam.html
- field.html
- my_form_1/
- feedback/
Default form contains javascript from {{ form.media }}
. If your customize templates we recomended instead of {{ form.media }}
include script in your base template footer:
<script type="text/javascript" src="/static/feedback/js/feedback.js"></script>
Or copy file content in your main.js file
About form customization:
-
To display form fields in the basic order, use default field output.
feedback.html:
{% load feedback_tags %} <form> ... {% for field in form.hidden_fields %}{{ field }}{% endfor %} {% for field in form.visible_fields %} {% show_field %} {% endfor %} ... </form>
In this example, hidden fields are rendered first, and then visible fields are rendered.
-
To separate fields into different groups:
forms.py:
from feedback.forms import BaseFeedbackForm class CallForm(BaseFeedbackForm): name = forms.CharField(widget=forms.TextInput(attrs={'data-set': 1})) email = forms.EmailField(widget=forms.TextInput(attrs={'data-set': 2})) phone = forms.CharField(widget=forms.TextInput(attrs={'data-set': 1}))
In this example we need to separate fields in two groups: "name" and "phone" in first group and "email" in second group.
feedback.html:
{% load feedback_tags %} <form> ... {% for field in form.hidden_fields %}{{ field }}{% endfor %} <div class="form__row"> <div class="form__col"> {% for field in form %} {% show_field field set 1 %} {% endfor %} </div> <div class="form__col"> {% for field in form %} {% show_field field set 2 %} {% endfor %} </div> </div> ... </form>
Field rendering is associated with code duplication. To avoid this, use the template tag {% show_field %}
.
Tag gets two parameters: "field" and "set" (optional). Rendered template get context and two additional varibles
- atts - field widget attributes form forms.py
- input_type - to separate different fields
field.html
<label {{ attrs }} {% if field.errors %}class="error"{% endif %}>
<span>{{ field.label }}</span>
{{ field }}
</label>
We can combine of field.name
and input_type
to identify any field:
{% if input_type == 'hidden' %}
{{ field }}
{% elif input_type == 'select' %}
<div class="{{ attrs.class }}{% if field.errors %} error{% endif %}">
<label>
<select required name="{{ field.html_name }}" id="id_{{ field.html_name }}">
{% for value, name in field.field.choices %}
<option {% if field.value|equal:value %}selected{% endif %} value="{{ value }}">{{ name }}</option>
{% endfor %}
</select>
{% if field.label %}<span>{{ field.label }}</span>{% endif %}
</label>
</div>
{% elif field.name == 'captcha' %}
{{ field }}
{% else %}
<div class="{{ attrs.class }}{% if field.errors %} error{% endif %}">
<label>
<span>{{ field.label }}</span>
{{ field }}
</label>
</div>
{% endif %}
-
Administrative interface: to connect the HTML-editor to the "success message" field, install
django_tinymce
package (tested for version 2.6.0)pip install django_tinymce==2.6.0
-
If you need additional protection, easy integration with Google reCaptcha v2. Package is available here:
pip install git+git://github.com/oldroute/django-nocaptcha-recaptcha.git