0

I have a signup form that works great. One feature of it is users can press "Add more +" and have more identical "instrument" and "level" select fields created. The model only saves the first "instrument" and "level" field and not the further ones created from the javascript function. How can I adjust my model to create further fields when the javascript function is called? I appreciate any help I get.

models.py

class User(AbstractBaseUser):
    instrument = models.CharField(max_length=255, choices=instrument_list)
    level = models.CharField(max_length=255, choices=level_list)

HTML

<div>
    <div class="items">
        <div id="ins">
            <div>
                {{ form.instrument }}
            </div>

            <div>
                {{ form.level }}
            </div>
        </div>
    </div>


    <div id="add_more">
        <button type="button" class="no_link" onclick="add_instrument()">Add more +</button>
    </div>
</div>

Javascript

var i = 0;
var original = document.getElementById('ins');

function add_instrument() {
    var clone = original.cloneNode(true);
    clone.id = "ins" + ++i;
    original.parentNode.appendChild(clone);
}
  • Just creating the new fields in the DOM is not enough, you'll need to create submittable forms with each request being handled in the controller either individually or iteratively using some sort of count of the form fields and then save the values. Check this similar post: https://stackoverflow.com/questions/5478432/making-a-django-form-class-with-a-dynamic-number-of-fields – Priyeshj Jun 27 '18 at 01:44

2 Answers2

0

What you're looking for are Django formsets in order to dynamically add or remove forms. Think, a form of forms. Here is Django's documentation on it: https://docs.djangoproject.com/en/2.0/topics/forms/formsets/ As well as two good tutorials that I used to understand and create a formset:

  1. https://medium.com/@taranjeet/adding-forms-dynamically-to-a-django-formset-375f1090c2b0
  2. https://whoisnicoleharris.com/2015/01/06/implementing-django-formsets.html
0

Your model is wrong. If an user can have more than one instrument/level pair (I assume instrument and level work together), you want a distinct "Instrument" model and a one to many relationship:

class User(AbstractBaseUser):
    # remove instrument and level fields


class Instrument(models.Model):
    user = models.ForeignKey(User, related_name="instruments")
    instrument = models.CharField(max_length=255, choices=instrument_list)
    level = models.CharField(max_length=255, choices=level_list)

then use a formset as explained in Jordy Mcnab's answer to allow the user to add new instruments.

NB : actually the proper relational model here would be an Instrument model and a many to many relationship valued with the user's level for this instrument:

class User(AbstractBaseUser):
    # remove instrument and level fields


class Instrument(models.Model):
    instrument = models.CharField(max_length=255, choices=instrument_list, unique=True)


class UserInstrument(models.Model):
    user = models.ForeignKey(User, related_name="instruments")
    level = models.CharField(max_length=255, choices=level_list)
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118