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()