How to pass dictionary from Django to JavaScript and use it to set checkbox states?

I’m trying to set checkbox states based on a dictionary from my Django backend but I can’t figure out how to properly pass the data to JavaScript and apply it to the checkboxes.

Here’s my model structure:

class UserProfile(models.Model):
    user_id = models.AutoField(primary_key=True)
    username = models.CharField(max_length=150)
    user_email = models.EmailField(max_length=150, unique=True)
    user_password = models.CharField(max_length=150)
    selection_data = models.JSONField(null=True, blank=True, default=dict)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    
    def get_user_info(self):
        return '{}-{}'.format(self.username, self.user_password)

My view function:

from django.shortcuts import render, redirect
from .models import UserProfile
import json

def seat_selection(request, user_id):
    profile = UserProfile.objects.get(user_id=user_id)
    
    if request.method == 'POST':
        selection_json = request.POST.get('selectionData')
        if selection_json:
            selection_dict = json.loads(selection_json)
            profile.selection_data = selection_dict
            profile.save()
    
    saved_selections = profile.selection_data
    print(saved_selections)
    
    return render(request, 'app/seats.html', {'saved_selections': saved_selections})

Template with checkboxes:

<!DOCTYPE html>
<html>
<head>
    <style>
        .seat-container {
            display: flex;
            justify-content: center;
            margin: 50px;
        }
        .seat-grid {
            transform: scale(2);
        }
    </style>
</head>
<body>
    <div class="seat-container">
        <form method="POST" id="seatForm">
            {% csrf_token %}
            <div class="seat-grid">
                <table>
                    <tr>
                        <td><input type="checkbox" name="position" id="A1"></td>
                        <td><input type="checkbox" name="position" id="A2"></td>
                        <td><input type="checkbox" name="position" id="A3"></td>
                    </tr>
                    <tr>
                        <td><input type="checkbox" name="position" id="B1"></td>
                        <td><input type="checkbox" name="position" id="B2"></td>
                        <td><input type="checkbox" name="position" id="B3"></td>
                    </tr>
                </table>
            </div>
            <button type="submit">Save Selection</button>
        </form>
    </div>
</body>
</html>

JavaScript code:

<script>
document.addEventListener('DOMContentLoaded', function() {
    document.querySelector('#seatForm').addEventListener('submit', function(event) {
        event.preventDefault();
        var selectionData = {};
        var inputs = document.querySelectorAll('input[type="checkbox"]');
        inputs.forEach(function(input) {
            selectionData[input.id] = input.checked;
        });
        
        document.querySelector('#selectionData').value = JSON.stringify(selectionData);
        this.submit();
    });
});

let savedData = {% autoescape off %}{{saved_selections}}{% endautoescape %};
for(const [key, value] of Object.entries(savedData)) {
    console.log(key, value);
}
</script>

I’m having trouble getting the dictionary data into JavaScript properly and then using it to check the appropriate checkboxes. How can I fix this?

The problem is timing - your checkbox restoration code runs outside the DOMContentLoaded listener, so it might fire before the DOM’s ready. I hit this same issue building a conference room booking system. Just wrap your restoration logic inside the event listener and add some error handling: javascript document.addEventListener('DOMContentLoaded', function() { // Restore saved checkbox states let savedData = {{ saved_selections|default_if_none:"{}" |safe }}; Object.keys(savedData).forEach(key => { const checkbox = document.getElementById(key); if (checkbox && savedData[key] === true) { checkbox.checked = true; } }); // Form submission handler document.querySelector('#seatForm').addEventListener('submit', function(event) { // your existing submit code }); }); Don’t forget the hidden input field that others mentioned. Also, default_if_none handles null database values better than just default.

You’re not handling null values when selection_data is empty. JSON parsing breaks if saved_selections is null or empty. I hit this same issue building a booking system last year.

Handle the None case in your template:

let savedData = {{ saved_selections|default:"{}"|safe }};
if (Object.keys(savedData).length > 0) {
    for (const [key, value] of Object.entries(savedData)) {
        const checkbox = document.getElementById(key);
        if (checkbox && typeof value === 'boolean') {
            checkbox.checked = value;
        }
    }
}

Add the missing hidden input field to your form. The default:"{}" filter gives you valid JSON even when the database field is null.

Your JavaScript collects the checkbox states but doesn’t restore them when the page loads. You’re missing the hidden input field and the restoration logic. Add this to your form: <input type="hidden" name="selectionData" id="selectionData"> Then fix your JavaScript to restore the states: javascript let savedData = {{ saved_selections|safe }}; if (savedData) { for (const [key, value] of Object.entries(savedData)) { const checkbox = document.getElementById(key); if (checkbox) { checkbox.checked = value; } } } I’ve used the |safe filter for Django-JS data passing before - it works better than disabling autoescape completely. Check your browser console first to make sure saved_selections actually has data.

You’re missing the hidden input field for selectionData in your form. Try using the |safe filter instead of turning autoescape off - it’s cleaner. Once you get the data in JS, just loop through and set document.getElementById(key).checked = value

Skip the Django template and JavaScript serialization headaches - just automate the whole thing. I’ve hit this same checkbox state mess in tons of projects. Manual approaches always turn into spaghetti code.

Latenode handles this workflow perfectly. It grabs your checkbox selections, pushes them through Django, and syncs everything back to your frontend automatically.

No more JSON serialization bugs, null value headaches, or DOM timing issues. Latenode just handles the data pipeline between your Django model and JavaScript.

I used it for a seat reservation system where users saved complex selection patterns. The automation killed all those annoying edge cases you get with manual coding.

Your code structure’s solid, but you’re doing way too much by hand. Let Latenode handle the data flow so you can focus on the actual app logic.

The main issue is that you’re missing a hidden input field to store the serialized data and your JavaScript isn’t actually setting the checkbox states. Add <input type="hidden" name="selectionData" id="selectionData"> inside your form. In your JavaScript, ensure you’re parsing the saved selections correctly and iterating through them to set the checkbox states when the page loads. Use code like the following: for (const [key, value] of Object.entries(savedData)) { document.getElementById(key).checked = value; }. This way, your checkboxes will reflect the stored states from your Django backend.

Two problems here: you’re missing the hidden input, and your JS runs before the checkboxes exist. Move your restoration code inside the DOMContentLoaded event listener (after you define savedData). Also make sure to check that savedData isn’t null or undefined before you loop through it.

check ur console output first - if saved_selections shows up as None or an empty dict in your view, that’s likely what’s breaking it. ur JS timing could also be the issue since ur accessing savedData before the DOM loads but outside the event listener.