Help with Dynamically Adding Forms to Formset!!

445 views
Skip to first unread message

Stephanie Socias

unread,
Mar 30, 2015, 4:37:38 PM3/30/15
to django...@googlegroups.com
Hello,

I'm having trouble creating a formset where I can dynamically add and delete items. I've tried many different approaches and can't get anything to work. I'm new to Django and have been at this for days. Can someone please help me!? I can send my code, post it, or do a screen share. Please let me know!! Any help would be greatly appreciated.

-Stephanie

Carl Meyer

unread,
Mar 30, 2015, 5:18:45 PM3/30/15
to django...@googlegroups.com
Hi Stephanie,
I'm afraid I don't have time in my day for a screen-share, but I'd be
happy to try to help, if you can link to a gist or paste showing your
current best effort, and explaining how it is not working.

FWIW, I've usually used this library for the JavaScript side of things:
https://github.com/jgerigmeyer/jquery-django-superformset

If you'd find real-time assistance more helpful, you could visit the
#django channel on FreeNode IRC; I and others are available to help out
there.

This is a challenging task you've tackled, even for experienced Django
developers, so it's not surprising that it's taking some time if you're
new to Django.

Carl

signature.asc

Bill Blanchard

unread,
Mar 30, 2015, 5:25:03 PM3/30/15
to django...@googlegroups.com
Hi Stephanie,
I've had success with the following jQuery library:


You can administer the formsets normally in your view and forms files.  Reference here:

Here is a code snippet of a template that I've written for my app.  You can modify accordingly to try to back into a solution:
...
...
<script src="{% static 'jquery.formset.js' %}"></script>
<script type="text/javascript">
    $(function() {
        $('.itinerary-bootstrap .formset').formset({
            prefix: '{{ formset.prefix }}',
            addText: 'Add Another Leg',
            deleteText: 'Remove Leg',
        })
    })
</script>
...
...
    <div id="itinerary-bootstrap" class="itinerary-bootstrap">
        {% for form in formset.forms %}
            <div class="formset">
                <div id="{{ form.prefix }}-row">
                    <div class="col-md-2">
                        <div class="row">
                            {{ form.date }}
                        </div>
                        <div class="row">
                            {{ form.ETD }}
                        </div>
                    </div>
                    <div class="col-md-4 col-md-offset-1">
                        <div class="row">
                            {{ form.origin }}
                        </div>
                        <div class="row">
                            {{ form.destination }}
                        </div>
                    </div>
                </div>
            </div>
        {% endfor %}
        {{ formset.management_form }}
        <br><br>
    </div>
....
....


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/5519BD9B.9080105%40oddbird.net.
For more options, visit https://groups.google.com/d/optout.

Lachlan Musicman

unread,
Mar 30, 2015, 5:26:42 PM3/30/15
to django...@googlegroups.com
Carl is right - this is a hard problem. I'm a mid level django
developer and I spent at least a week trying a number of solutions
(and doing the other, non Django, parts of my job).

The one that ended up working for me was the django-dynamic-formset
javascript library.

https://github.com/elo80ka/django-dynamic-formset

It took some tinkering, but that was because my brain was fried after
a week of trying to solve it :)

L.
------
It is through this shadowy emptiness (of negative space) that we
walk, talk, see, and live; negative space is the impossible cellophane
layer that drapes the known world and is invisible to all but to the
most perceptive minds.

It is possible to learn to see negative space though, in both the
visual and imagined worlds. The first step is developing the ability
to see, and the second is learning — as romantic poet John Keats put
it — to be “capable of being in uncertainties, mysteries, doubts,
without any irritable reaching after fact & reason.”
----
Seeking Genius in Negative Space, Chris Messina
https://medium.com/genius-week/seeking-genius-in-negative-space-4e7c755f641f

Stephanie Socias

unread,
Mar 30, 2015, 6:03:38 PM3/30/15
to django...@googlegroups.com
Thank you all SO much for your advice. Even just hearing that this is a complicated problem and that it's not just me, really helps.

I will post my code shortly. I'm now trying to incorporate some of your feedback.

Bill,
How do I set/use the 'addText' and 'deleteText' variables from the script in the template? That is probably a really dumb question but I have just about zero experience with javascript/jquery.

Thank you!
Stephanie

On Mon, Mar 30, 2015 at 5:18 PM, Carl Meyer <ca...@oddbird.net> wrote:

Carl

--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/3UR_6HtcnY0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.

Bill Blanchard

unread,
Mar 30, 2015, 6:32:25 PM3/30/15
to django...@googlegroups.com

Hi Stephanie,
The addText and deleteText variables are the hyperlink text that is displayed on the page.

You can remove them or modify accordingly. I believe the default values are Add Form and Remove Form if you do not explicitly declare them in the javascript function.

You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.

Stephanie Socias

unread,
Mar 30, 2015, 8:19:51 PM3/30/15
to django...@googlegroups.com
Thank you, Bill. That was silly of me. I'm just confused on where/how those actual links are displayed. I can't get them to show...


{% load crispy_forms_tags %}
<script src="{{ STATIC_URL }}js/addAuthor.js" type="text/javascript"></script>
<script src="{{ STATIC_URL }}js/jquery.formset.js"></script>
<script type="text/javascript">
    $(function() {
        $('#authorFormset .formset').formset({
            prefix: '{{ formset.prefix }}',
            addText: 'Add Author',
            deleteText: 'Remove Author',
        })
    })
</script>

<form action="{% url 'data:register' %}" method="post" enctype="multipart/form-data">


  <div class="container">
    <div class="row" style="margin-top: 30px">
      <div class="col-md-10 col-md-offset-1">
        {{ dataset_form.media }}
        {% crispy dataset_form %}
        {% crispy facility_form %}
        {% crispy contact_form %}
       
        <div id="authorFormset" class="formset">

        {% for form in formset.forms %}
            <div class="formset">
                <div id="{{ form.prefix }}-row">
                    <div class="col-md-2">
                        <div class="row">
                            {{ form.first_name }}
                        </div>
                        <div class="row">
                            {{ form.last_name }}

                        </div>
                    </div>
                    <div class="col-md-4 col-md-offset-1">
                        <div class="row">
                            {{ form.email }}
                        </div>
                        <div class="row">
                            {{ form.role }}

                        </div>
                    </div>
                </div>
            </div>
        {% endfor %}
        {{ formset.management_form }}
        <br><br>
    </div>
  
      </div>
    </div>
  </div>

  <div class="container">
    <div class="row">
      <div class="col-md-10 col-md-offset-1">
        <a role="button" class="btn btn-lg btn-default" href="{% url 'data:data_home' %}">Cancel</a>
        <input type="submit" class="btn btn-lg btn-success pull-right" value="Proceed to Data Upload">
      </div>
    </div>
  </div>
</form>

Lachlan Musicman

unread,
Mar 30, 2015, 8:25:08 PM3/30/15
to django...@googlegroups.com
I think here:

<div id="authorFormset" class="formset">
{% for form in formset.forms %}
<div class="formset">

you need to move the id

<div class="formset">
{% for form in formset.forms %}
<div id="authorFormset" class="formset">

cheers
L.
------
It is through this shadowy emptiness (of negative space) that we
walk, talk, see, and live; negative space is the impossible cellophane
layer that drapes the known world and is invisible to all but to the
most perceptive minds.

It is possible to learn to see negative space though, in both the
visual and imagined worlds. The first step is developing the ability
to see, and the second is learning — as romantic poet John Keats put
it — to be “capable of being in uncertainties, mysteries, doubts,
without any irritable reaching after fact & reason.”
----
Seeking Genius in Negative Space, Chris Messina
https://medium.com/genius-week/seeking-genius-in-negative-space-4e7c755f641f


> https://groups.google.com/d/msgid/django-users/CAOw%3DD6V45R64%3D0o2W9miXJzy_xqBW5YLooTS7ef9DzNuPATxiQ%40mail.gmail.com.

Bill Blanchard

unread,
Mar 30, 2015, 8:29:41 PM3/30/15
to django...@googlegroups.com
Hi Stephanie,
You have two jQuery selectors in your formset function and I'm not sure if that will cause an issue or not.  Also, I don't think you need to use an id in the div tag (that was probably left over from when I was bashing my head against this).  Try naming the outer div class something not "formset" since you'll get two selections based on the classes you're using.  Try this:
...
$(function() {
        $('.authorFormset').formset({
....
<div class="authorFormset">

        {% for form in formset.forms %}
            <div class="formset">
                <div id="{{ form.prefix }}-row">
                    <div class="col-md-2">

...

Also, try looking at the javascript console in your browser to see if you get any error messages.  Hope this helps!

Bill

Stephanie Socias

unread,
Mar 30, 2015, 8:29:58 PM3/30/15
to django...@googlegroups.com
hmmm still not showing up....do I need to add an actual button holder somewhere? I think the js takes care of that but I don't see any links

Stephanie Socias

unread,
Mar 30, 2015, 8:34:18 PM3/30/15
to django...@googlegroups.com
Thank you, Bill! I'm getting a TypeError that $(...).formset is not a function
I'll see what's up!

Bill Blanchard

unread,
Mar 30, 2015, 8:39:39 PM3/30/15
to django...@googlegroups.com
You could have an import error somewhere/somehow with the jquery.formset.js file.  Also, you might need to import the jquery library in your application (I import mine in my base template, so that might be why I forgot about it).

Stephanie Socias

unread,
Mar 30, 2015, 9:55:10 PM3/30/15
to django...@googlegroups.com
Sorry to ask here again but I still can't get the imports right for some reason. I get the error:

TypeError: $(...).formset is not a function
$('.authorFormset').formset({



I have this in the head of my base.html:

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="{{ STATIC_URL }}js/jquery.formset.js" type="text/javascript"></script>



And then my homepage.html:

{% load crispy_forms_tags %}

<script type="text/javascript">
    $(function() {
        $('.authorFormset').formset({

            prefix: '{{ formset.prefix }}',
            addText: 'Add Author',
            deleteText: 'Remove Author',
        })
    })
</script>

<form action="{% url 'data:register' %}" method="post" enctype="multipart/form-data">


  <div class="container">
    <div class="row" style="margin-top: 30px">
      <div class="col-md-10 col-md-offset-1">
        {{ dataset_form.media }}
        {% crispy dataset_form %}
        {% crispy facility_form %}
        {% crispy contact_form %}
       
        <div class="authorFormset">
        {% for form in formset.forms %}
            <div class="formset">
                <div id="{{ form.prefix }}-row">
                    <div class="col-md-2">

Bill Blanchard

unread,
Mar 30, 2015, 10:20:43 PM3/30/15
to django...@googlegroups.com
Sounds like a stupid question, but are you 100% sure that this is resolving correctly?

<script src="{{ STATIC_URL }}js/jquery.formset.js" type="text/javascript"></script>

You can check by monitoring the network tab when you go to inspect element in a chrome browser (or whatever the firefox equivalent is). When you refresh the page, it will tell you if that file is found or not.

If it's found, then I might be stumped, or it might be some kind of import issue with the base jquery file or a conflict.

If it's not found, you'll have to troubleshoot the issue related to pointing to the correct source location.

Bill



Lachlan Musicman

unread,
Mar 30, 2015, 10:30:40 PM3/30/15
to django...@googlegroups.com
Just checking you have

{% load staticfiles %} in your templates - you will need in both iirc?
------
It is through this shadowy emptiness (of negative space) that we
walk, talk, see, and live; negative space is the impossible cellophane
layer that drapes the known world and is invisible to all but to the
most perceptive minds.

It is possible to learn to see negative space though, in both the
visual and imagined worlds. The first step is developing the ability
to see, and the second is learning — as romantic poet John Keats put
it — to be “capable of being in uncertainties, mysteries, doubts,
without any irritable reaching after fact & reason.”
----
Seeking Genius in Negative Space, Chris Messina
https://medium.com/genius-week/seeking-genius-in-negative-space-4e7c755f641f


> https://groups.google.com/d/msgid/django-users/CAP7uEDKhA%2B5n9Zd%3DuM5KaoKFEDRYxkVvdRSK50UrWgKjAMkiaA%40mail.gmail.com.

Stephanie Socias

unread,
Mar 30, 2015, 10:46:54 PM3/30/15
to django...@googlegroups.com
Aaaaah finally!
I had jquery.formset.js in my base.html header. I moved it to my     {% block footer_js %}  and it worked!! Not sure why that's the case....anyways, now on to the next issue ([u'ManagementForm data is missing or has been tampered with']) but I think I can hopefully fix that one!

Thank you SOOOOOOO much!!

Bill Blanchard

unread,
Mar 30, 2015, 10:50:54 PM3/30/15
to django...@googlegroups.com

I fought with formsets for a week when I started. Glad I could pay it forward a bit.

Lachlan Musicman

unread,
Mar 30, 2015, 10:58:15 PM3/30/15
to django...@googlegroups.com
likewise. likewise.
------
It is through this shadowy emptiness (of negative space) that we
walk, talk, see, and live; negative space is the impossible cellophane
layer that drapes the known world and is invisible to all but to the
most perceptive minds.

It is possible to learn to see negative space though, in both the
visual and imagined worlds. The first step is developing the ability
to see, and the second is learning — as romantic poet John Keats put
it — to be “capable of being in uncertainties, mysteries, doubts,
without any irritable reaching after fact & reason.”
----
Seeking Genius in Negative Space, Chris Messina
https://medium.com/genius-week/seeking-genius-in-negative-space-4e7c755f641f


> https://groups.google.com/d/msgid/django-users/CAP7uED%2Bkj3FEjQgHLwVtKtCnqY2ZuTaPoOLPtko3bO%3Dy2TWcGg%40mail.gmail.com.

Stephanie Socias

unread,
Mar 31, 2015, 12:11:42 AM3/31/15
to django...@googlegroups.com
Hello Again,

I don't mean to take advantage of your kindness and generosity in helping me- I'm so appreciative....I'm just still stuck on the ValidationError
[u'ManagementForm data is missing or has been tampered with']

Error during template rendering

In template /Users/stephani/git/data/data/databank_fr/templates/data/register_dataset.html, error at line 6

ManagementForm data is missing or has been tampered with

1{% load crispy_forms_tags %}
2
3<script type="text/javascript">
4 $(function() {
5 $('.authorFormset').formset({
6 prefix: '{{ formset.prefix }}',
7 addText: 'Add Author',
8 deleteText: 'Remove Author',
9 })
10 })
11</script>
12
13<form action="{% url 'databank:register' %}" method="post" enctype="multipart/form-data">
14
15
16 <div class="container">

Traceback Switch to copy-and-paste view

  • /Users/stephaniesocias/.virtualenvs/databank2/lib/python2.7/site-packages/django/core/handlers/base.py in get_response
    1.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
      ...
  • /Users/stephan/git/data/databank_fr/databa/apps/databank/views.py in register
    1.         'formset': author_formset, 'author_formset_helper': author_formset_helper, 'contact_form': contact_form, 'terms_form': terms_form})
      ...
  • /Users/stephan/.virtualenvs/data/lib/python2.7/site-packages/django/shortcuts.py in render
    1.     return HttpResponse(loader.render_to_string(*args, **kwargs),
      ...
  • /Users/stephan/.virtualenvs/data/lib/python2.7/site-packages/django/template/loader.py in render_to_string
    1.         return t.render(context_instance)
      ...




I read that it might be an issue with having a form and a formset next to each other? If I don't use the "add" or "remove" links, I can submit my page (which contains other forms in addition to my formset) with just one form of the formset. But, when I do 'add' or 'delete' to add another form to the formset, I get the error. The post data, though, does seem to register the additional form...

views.py

def register(request):

dataset_form = DatasetForm()
facility_form = FacilityForm()
contact_form = FacilityContactForm()
terms_form = TermsForm()

author_formset = AuthorFormset(prefix='author')
author_formset_helper = AuthorFormsetHelper()

if request.method == 'POST':
dataset_form = DatasetForm(request.POST, request.FILES)
facility_form = FacilityForm(request.POST)
author_formset = AuthorFormset(data=request.POST, prefix='author')


contact_form = FacilityContactForm(request.POST)

return render(request, 'databank/register.html', {'dataset_form': dataset_form, 'facility_form': facility_form,
'formset': author_formset, 'author_formset_helper': author_formset_helper, 'contact_form': contact_form, 'terms_form': terms_form})




Stephanie Socias

unread,
Apr 7, 2015, 11:00:21 AM4/7/15
to django...@googlegroups.com
Thank you SO much to Bill Blanchard for helping me figure this out!

The main issue was that {{ formset.management_form }} was in the div being used by the javascrip to add/delete forms. So, it was causing the error. We moved it out of the div, just before the closing </form> tag and it worked great!
...
Reply all
Reply to author
Forward
0 new messages