# Loop through multiplechoicefield

**URL:** https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119
**Category:** Using Django
**Created:** [June 24, 2020, 9:06pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119 "2020-06-24T21:06:38Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 24, 2020, 9:06pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/1 "2020-06-24T21:06:38Z")

</div>

Hi I am new to Django and have a question about a form I have built.

The form I have created consists of one multiplechoicefield, with the choices being a dictionary of vacations.

```
interests = forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple, choices=vacations.items)

```

The dictionary has a string as a key (states), and a list of strings as values (cities in the state). Ideally, I am envisioning looping through the keys displaying one at a time, and if the user clicks on the key, then show the values for the key and let the user click on many options out of the values for that key.

Example: Loop through states as buttons, and if the user clicks on the state, display the cities as buttons and allow the user to select multiple cities in the state and proceed to next state. Proceed to next state in the “vacation” dictionary.

All help is really appreciated! Thank you!

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 24, 2020, 9:34pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/2 "2020-06-24T21:34:59Z")

</div>

Sounds like this is going to involve some JavaScript. Are you currently using a JavaScript framework such as jQuery, React, Angular, or Vue?

If not, how comfortable are you with JavaScript and AJAX?

Keep in mind that once a page has been sent from the server to the browser, the server doesn’t have any involvement any more. The server can send out the list of states to the browser, but there’s going to need to be some code _running in the browser_ that will cycle through those states and taking action on a button press.

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 24, 2020, 9:58pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/3 "2020-06-24T21:58:41Z")

</div>

Hi- thank you for the reply.

I know how to use javascript (I actually created a dummy version of what I want just with HTML and javascript but I don’t know how to link that to django databases). AJAX I’m not as familiar with. And no, I am not currently using a Javascript framework. How could I use those in django to acomplish what I want?

Thank you again.

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 24, 2020, 10:29pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/4 "2020-06-24T22:29:26Z")

</div>

They’re separate functions. You would write your JavaScript that performs all the UX functions. Then, when you need data from the server, you issue an AJAX call to the server to send or receive data as necessary. Your Django code then defines the URLs being used by AJAX as being assigned to views that accept or generate data to be returned to the JavaScript call.

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 25, 2020, 6:31pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/5 "2020-06-25T18:31:13Z")

</div>

Hi, thank you for the responses. With your tips, I’ve been trying to implement AJAX with the javascript, but I am coming across an error I cant figure out.

views.py:

> ```
> @login_required
> def questions(request):
> if request.method == 'POST':
> person = request.user.profile
> person.interests = request.POST.['interests']
> person.save()
> messages.success(request, f'Your interests have been updated')
> return redirect('profile')
> 
> ```

AJAX javascript script:

```
function subcatClicked(ID){
    $.ajax({
         url: '/update_interests/',
         data: {'interests': ID},
         type: 'POST'
       }).done(function(){
         console.log("Done");
       }); 

```

The error I am getting is

> # MultiValueDictKeyError at /questions/
> 
> ‘interests’

Looking online, I tried solve this by changing this line in views:

> person.interests = request.POST.[‘interests’]

to this:

> person.interests = request.POST.get(‘interests’)

But that just gets me a new error which is:

> # IntegrityError at /questions/
> 
> NOT NULL constraint failed: users\_profile.interests

If you can help me understand how to fix this problem I would appreciate it a lot. Thanks in advance.

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 25, 2020, 6:34pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/6 "2020-06-25T18:34:43Z")

</div>

What does your profile model look like?

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 25, 2020, 10:17pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/7 "2020-06-25T22:17:43Z")

</div>

Models.py:

```
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete = models.CASCADE)
    image = models.ImageField(default = 'default.jpg', upload_to = 'profile_pics')
    interests = models.TextField(default = "")

    def __str__ (self):
        return f'{self.user.username} Profile'

    def save(self):
        super().save()
        img = Image.open(self.image.path)

        if img.height > 300 or img.width > 300:
            output_size = (300,300)
            img.thumbnail(output_size)
            img.save(self.image.path)
```

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 25, 2020, 10:47pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/8 "2020-06-25T22:47:21Z")

</div>

So the second error caused by:

> [@bgivner](#):
>
> person.interests = request.POST.get(‘interests’)

indicates that there isn’t a value being supplied in the POST. By default, get returns None if the key isn’t present. To avoid that specific error, you would want to use:  
`person.interests = request.POST.get('interests', "")`

But, that doesn’t address why it’s null to begin with.

First, I really hope you’re using a version of jQuery newer than 1.9 - in which case you should be using `method: 'POST'` and not `type: 'POST'`.

Give these changes a try.

Ken

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 25, 2020, 11:03pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/9 "2020-06-25T23:03:08Z")

</div>

Made the changes, thank you.

With the line you suggested, it is entering whatever comes second in the parentheses, which in this case

`person.interests = request.POST.get('interests', "")`

is empty. How can I get it to add what `'interests'` maps to? I actually want to concatenate it to the existing textfield, creating a list of strings in the textfield.

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 25, 2020, 11:07pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/10 "2020-06-25T23:07:26Z")

</div>

Probably the easiest thing I can think to do to verify what’s going across the wire is to look at the network tab in the browser’s developer tools to see exactly what’s being posted in the ajax call. My guess would be that what you’re actually sending isn’t what you think you’re sending.

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 26, 2020, 5:57pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/11 "2020-06-26T17:57:32Z")

</div>

So I see now that, actually, I’m getting an error in the browser:

“$.ajax is not a function”

I downloaded jquery-django using pip, but for some reason it is not identifying my ajax calls. In my `INSTALLED_APPS` I have `'django.contrib.staticfiles'` and `'jquery'` already.

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 26, 2020, 6:01pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/12 "2020-06-26T18:01:56Z")

</div>

But are you including the jquery scripts in your templates being rendered out to the browser?

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 26, 2020, 6:18pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/13 "2020-06-26T18:18:34Z")

</div>

What should I include as the src in my javascript script?

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 26, 2020, 6:21pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/14 "2020-06-26T18:21:42Z")

</div>

Sorry, I’m not following what you’re asking here.

Typically, javascript scripts and css files are rendered in templates as standard `script` and `link` tags in your html. From the Django perspective, they’re static files - just like any other static file that may be handled.

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 26, 2020, 6:34pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/15 "2020-06-26T18:34:03Z")

</div>

Thank you for all the help and quick responses so far, I appreciate it a lot.

Here is my entire template. The error I’m getting is in the ajax call all the way at the bottom in the `subcatClicked(ID)` function.

```
{% extends "survey/base.html" %}
{% block content %}

<form id="regForm" method = "POST" action="">
  {% csrf_token %}
  <div class = "tab">
    <h1> Here are a few questions to get you started</h1>
    <button type="button" class = "bigButton bigButton1" id="okBtn" onclick="okNext(1)">OK</button>
  </div>

  {% for tag, subcats in questionList.items %}
  <div class = "tab">
    <h1> Are you interested in a(n) {{tag}} group?</h1>
    <button type = "button" class = "bigButton bigButton1" id="noBtn" onclick="noNext(1)">No</button>
    <button type = "button" class = "bigButton bigButton1" id="maybeBtn" onclick = yesNext()>Maybe</button>
    <button type = "button"class = "bigButton bigButton1" id="yesBtn" onclick= "yesNext()">Yes</button>
    <div>
      <button type = "button" class = "button button1" id="prevBtn1" onclick="okNext(-1)">Previous</button>
    </div>
  </div>

      <div class = "subcat">
        <h1>Click on the ones you're interested in</h1>
          {% for subcat in subcats %}
          <input type="button" class = "subcatButton subcatButton1" id="subBtns_{{subcat}}" onclick = subcatClicked("{{subcat}}") value = "{{subcat}}">
          {% endfor %}
          <div>
              <button type="button" class = "button button1" id="nextBtn" onclick="inSubcatNext(1)">Next</button>
          </div>
      </div>

  <div class = "endtab">
    <h1>Great, thanks for answering!</h1>
    <button type="submit" class = "Button Button1" id="exitBtn" href="{% url 'survey-home'%}" >Exit</button>
  </div>

  {% endfor %}

  <p>
    <div style="text-align:center;margin-top:40px;">
      <span class="step"></span>
      <span class="step"></span>
      <span class="step"></span>
      <span class="step"></span>
    </div>
  </p>

</form>

<script src="{{ STATIC_URL }}jquery.js">
var currentTab = 0; // Current tab is set to be the first tab (0)
var currentSubcat = 0;
showTab(currentTab); // Display the current tab

function showTab(n) {
  var x = document.getElementsByClassName("tab");
  x[n].style.display = "block";

    if(n == x.length-1){
       document.getElementById("noBtn").style.display = "Submit";
       document.getElementById("yesBtn").style.display = "Submit";
    }
    else{
        document.getElementById("noBtn").style.display = "inline";
        document.getElementById("yesBtn").style.display = "inline";
    }

  // ... and run a function that displays the correct step indicator:
  fixStepIndicator(n)
}

function showSubcat(n){
  var y = document.getElementsByClassName("subcat");
  y[n].style.display = "block";

  // ... and run a function that displays the correct step indicator:
  fixStepIndicator(n)
}

function okNext(n){
  var x = document.getElementsByClassName("tab");
  var y = document.getElementsByClassName("subcat");
  x[currentTab].style.display = "none";
  if(y[currentSubcat].style.display != "none"){
      y[currentSubcat].style.display = "none"
  }
  currentTab = currentTab + n;
  if(currentSubcat != 0){
    currentSubcat = currentSubcat + n;
  }

  showTab(currentTab);
}

function noNext(n) {
  var x = document.getElementsByClassName("tab");
  var y = document.getElementsByClassName("subcat");

  // Hide the current tab:
  x[currentTab].style.display = "none";
  y[currentSubcat].style.display = "none";
  currentTab = currentTab + n;
  currentSubcat = currentSubcat + n;

  if (currentTab >= x.length) {
    document.getElementById("regForm").submit();
    return false;
  }

  showTab(currentTab);
}

function yesNext(){

  var y = document.getElementsByClassName("subcat");
  var x = document.getElementsByClassName("tab");

  showSubcat(currentSubcat)
 }

function fixStepIndicator(n) {
  var i, x = document.getElementsByClassName("step");
  for (i = 0; i < x.length; i++) {
    x[i].className = x[i].className.replace(" active", "");
  }
  x[n].className += " active";
}

function inSubcatNext(n){

  var y = document.getElementsByClassName("subcat");
  var x = document.getElementsByClassName("tab");

  y[currentSubcat].style.display = "none";
  x[currentTab].style.display = "none";

  currentTab = currentTab + 1;
  currentSubcat = currentSubcat + 1;

  showTab(currentTab);
}

function subcatClicked(ID){
    //ajax call to server to send the subcategory clicked by the user to the database to 
    //register
    $.ajax({
         url: '/update_interests/',
         data: {'interests': ID},
         method: 'POST'
       }) 

  if(document.getElementById(ID).style.backgroundColor != "blue"){
    document.getElementById(ID).style.backgroundColor = "blue"
  }
  else{
    document.getElementById(ID).style.backgroundColor = "white"
  }
}
</script>
{% endblock content%}

```

What am I missing to get the ajax call recognized?

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [June 26, 2020, 8:28pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/16 "2020-06-26T20:28:28Z")

</div>

What does your survey/base.html template look like?

Also, I had assumed from the use of the $.ajax call in your earlier snippet that you were currently using jQuery, but the rest of your code looks like standard JavaScript. I’m guessing then that you’re not using jQuery for anything at the moment?

---

<div class="post-metadata">

### Author: ![bgivner](https://avatars.discourse-cdn.com/v4/letter/b/ed8c4c/32.png) [@bgivner](https://forum.djangoproject.com/u/bgivner)
#### Post date: [June 28, 2020, 5:58pm UTC](https://forum.djangoproject.com/t/loop-through-multiplechoicefield/3119/17 "2020-06-28T17:58:21Z")

</div>

Thank you, I realized that on my survey/base.html I was using the slim version of jquery, which didn’t support ajax.

Fixing that issue, the error I come across is:  
`POST http://localhost:8000/questions/ 403 (Forbidden)`

Does this have to with the csrf token?

UPDATE: I found I had to pass through the csrf token in the ajax call for every POST.

Thank you for all the help!
