django-addanother documentation¶
django-addanother provides you with add-another and edit-related buttons for forms outside the Django administration interface. It also provides an optional integration with django-select2.
Supported Django versions: 1.8, 1.9, 1.10 (others may work well though)
Getting started¶
How to Install¶
pip install django-addanother
.- Add
'django_addanother'
to yourINSTALLED_APPS
. - Make sure static
'django.contrib.staticfiles'
and'django.contrib.admin'
are part of yourINSTALLED_APPS
.
Demo¶
To run the demo, clone the repository, run test_project/manage.py migrate
and test_project/manage.py runserver
and then go to http://localhost:8000
.
How to Use¶
1. Add the add-another button¶
Wrap django_addanother.widgets.AddAnotherWidgetWrapper
around your widget to show the add-another button next to it.
For example, let’s say we want to add add-another buttons to a model form:
from django.core.urlresolvers import reverse_lazy
from django_addanother.widgets import AddAnotherWidgetWrapper
class FooForm(forms.ModelForm):
class Meta:
...
widgets = {
'sender': AddAnotherWidgetWrapper(
forms.Select,
reverse_lazy('person_create'),
),
'recipients': AddAnotherWidgetWrapper(
forms.SelectMultiple,
reverse_lazy('person_create'),
)
}
This will add an add-another button next to the sender
and recipients
fields. When clicked, these will open the 'person_create'
URL in a popup.
Important
Be sure to include form media and jQuery in your templates:
{{ form }}
<script src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
{{ form.media }}
2. Make your view popup-compatible¶
Note
This assumes you’re using Django’s generic CreateView
. django-addanother doesn’t support function-based views at the point of writing. You’ll have to convert any function-based views to Class Based Views first.
Making your CreateView
compatible with django-addanother is as simple as making it inherit the django_addanother.views.CreatePopupMixin
class:
from django_addanother.views import CreatePopupMixin
class PersonCreate(CreatePopupMixin, CreateView):
model = Foo
...
This overwrites your view’s form_valid()
method to return a special JavaScript response in case a form has been submitted from a popup.
You may want to hide header, footer and navigation elements for the popups. When the create view is opened in a popup, the view.is_popup
template variable is set:
{% if not view.is_popup %} <nav>...</nav> {% endif %}
Advanced topics¶
Select2 Integration¶
django-addanother provides optional lightweight integration with django-select2.
Usage example:
from django_addanother.contrib.select2 import Select2AddAnother
class FooForm(forms.ModelForm):
class Meta:
...
widgets = {
'sender': Select2AddAnother(reverse_lazy('person_create')),
}
See Select2 Widgets Reference for a list of provided widgets.
How it Works¶
Note
django-addanother works exactly like the add-another and edit-related features in Django’s admin.
django-addanother works twofold: Firstly, it adds an add-another and an edit-related button next to your form fields. When one of these buttons is clicked, a special popup window with the “inline” creation form is opened.
The popup window isn’t much different from your usual form handling views. The main difference is that when the form has been submitted and validated successfully, after saving the newly created object, the user is not redirected to the view’s success_url
. Instead, a special JavaScript-only response is being sent to the browser, adding the new object to the selection (or modifying the option) in the original window and closing the popup window.
Any CreateView
or UpdateView
can be made compatible with django-addanother. When opened in a popup, the view gets appended the ?_popup=1
GET parameter, which is how the view knows when to respond with its special JavaScript response. This special handling is taken care of in django_addanother.views.CreatePopupMixin
and django_addanother.views.UpdatePopupMixin
, whose usage is explained in How to Use.
Reference¶
Views Reference¶
Widgets Reference¶
Select2 Widgets Reference¶
django-select2 Widget | ...AddAnother |
...EditSelected |
...AddAnotherEditSelected |
---|---|---|---|
Select2Widget |
Select2AddAnother |
Select2EditSelected |
Select2AddAnotherEditSelected |
HeavySelect2Widget |
HeavySelect2AddAnother |
HeavySelect2EditSelected |
HeavySelect2AddAnotherEditSelected |
Select2MultipleWidget |
Select2MultipleAddAnother |
Select2MultipleEditSelected |
Select2MultipleAddAnotherEditSelected |
HeavySelect2MultipleWidget |
HeavySelect2MultipleAddAnother |
HeavySelect2MultipleEditSelected |
HeavySelect2MultipleAddAnotherEditSelected |
HeavySelect2TagWidget |
HeavySelect2TagAddAnother |
HeavySelect2TagEditSelected |
HeavySelect2TagAddAnotherEditSelected |
ModelSelect2Widget |
ModelSelect2AddAnother |
ModelSelect2EditSelected |
ModelSelect2AddAnotherEditSelected |
ModelSelect2MultipleWidget |
ModelSelect2MultipleAddAnother |
ModelSelect2MultipleEditSelected |
ModelSelect2MultipleAddAnotherEditSelected |
ModelSelect2TagWidget |
ModelSelect2TagAddAnother |
ModelSelect2TagEditSelected |
ModelSelect2TagAddAnotherEditSelected |