Django JSONField values aren't returned as a correct JSON-format in template when extracted using javascript

I have a model like


class UserGroup(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, unique=False, related_name="group_owner")
    name = models.CharField(max_length=128)
    group_users = models.JSONField(models.EmailField(), default=list, blank=True)

    def get_absolute_url(self):
        return reverse("user_group_instance", kwargs={"pk": self.pk})

now, in my in another app I filter for a list of UserGroup instances for the given user, and I parse that query-set to a ModelMultipleChoiceField.

That works fine and such, the issue is that I want to extract the group_users in the template and add them to an array, using java-script, thus I have create a div which stores the (I would assume) json-array in the data-members attribute

<div id="group-modal">
        {% for group in form.groups.field.queryset %}
            <label>
                <input type="checkbox" class="group-checkbox" value="{{ group.id }}" data-members="{{ group.group_users|safe }}">
                {{ group.name }}
            </label>
            <br>
        {% endfor %}

</div>

now, when I in javascript get the data from the data-members the returned string is not a json-object e.g it is "['hello@world', 'foo@bar']".

The javascript is (simplified)

document.getElementById("save-groups").addEventListener("click", function() {
            let selectedPeople = [];
            document.querySelectorAll(".group-checkbox:checked").forEach(checkbox => {
                let members = JSON.parse(checkbox.getAttribute("data-members"));
                selectedPeople = [...new Set([...selectedPeople, ...members])]; 
            });

and the JSON.parse fails. I simply cannot wrap my head around why; I don't do any manually serialization of the json-data thus I let django do that stuff.

I could work around it by do some regex replacement, but I rather figure out what the issue is

I'm not sure that you need to pass the EmailField as the encoder for the JSONField. If you want to ensure that the value from that field ends up as JSON in the template rather than a python dict you can create a custom decoder:

import json

class CustomDecoder(json.JSONDecoder):
    def decode(self, obj):
        return json.dumps(super().decode(obj))
    

class Order(models.Model):
    sku_id = models.CharField(max_length=10)
    group_users = models.JSONField(decoder=CustomDecoder, blank=True)

Then saving {"email_address": "foo@bar.com"}" will end up as JSON in your template that can be passed to JSON.parse()

Вернуться на верх