Privacy Policy
Snippets index

  Share queryset between Django and javascript

templagetags/utils.py

import json
from django.utils.safestring import mark_safe
from django.core import serializers
from django.utils.encoding import is_protected_type
from django.core.serializers.json import DjangoJSONEncoder

@register.filter
def queryset_as_json(qs):
    """
    Sample usage:
        {{user.list_tipi_movimento|queryset_as_json}}
    """
    json_data = serializers.serialize("json", qs)
    return mark_safe(json_data)


def object_as_dict(obj):
    data = {}

    for field in obj._meta.local_fields:
        # Code stolen from Serializer
        value = field.value_from_object(obj)
        # Protected types (i.e., primitives like None, numbers, dates,
        # and Decimals) are passed through as is. All other values are
        # converted to string first.
        if is_protected_type(value):
            data[field.name] = value
        else:
            data[field.name] = field.value_to_string(obj)

    # Collect ids of M2M related items
    for field in obj._meta.get_fields():
        if field.is_relation and field.many_to_many:
                data[field.name] = [str(o.id) for o in getattr(obj, field.name).all()]

    return data


@register.filter
def object_as_json(obj):
    """
    Sample usage:
        {{original|object_as_json}}
    """

    try:
        data = object_as_dict(obj)
    except:
        data = {}

    json_data = json.dumps(data, cls=DjangoJSONEncoder)
    return mark_safe(json_data)

We these templatetags, you can easily share querysets or single records as global javascript variables:

my_template.html

{% block extrajs %}
  {{ block.super }}
  <script>
        posts_qs = {{posts|queryset_as_json}};
        post = {{original.post|object_as_json}};
  </script>
{% endblock %}

utils.js

jQuery helper to navigate the serialized queryset and search for a specific object:

function lookup_queryset(qs, model, pk) {
/*
    Find a specific record into serialized queryset;
*/
    obj = null;
    $.each(qs, function(index, value) {
        if (value.pk == pk && value.model == model) {
            obj = value;
            return false;
        }
    });
    return obj;
}
Sample data structure:

posts_qs = [
    {
        "pk": "6fd32724-54f4-4174-9e38-1888ebf5da06"
        "model": "backend.post",
        "fields": {"subject": "the subject", "data": ...},
    },
    ...
];

Sample usage:

function OnTipoMovimentoChange() {
    var selected = $('input[name=tipo_movimento]:checked', '#movimento_form').val();
    if (selected) {
        var obj = lookup_queryset(posts_qs, "backend.tipomovimento", selected);
        if (obj) {
            ...
        }
    }
}

If you need to serialize nested structures, use a DRF serializer as follows:

from django import template
from django.utils.safestring import mark_safe
from rest_framework.renderers import JSONRenderer
from backend.serializers import LinkSerializer

register = template.Library()


@register.filter
def serialize_links(queryset):
    """
    Sample usage:

        var QUERYSET_LINKS = {{links|serialize_links}};

    Returns a JSON-serialized dictionary, where the row id is the key;
    Example:

        data:
        {
            '29cfcecf-359f-448d-b408-5e613cd496e7': OrderedDict([
                ('id', '29cfcecf-359f-448d-b408-5e613cd496e7'),
                ('category', OrderedDict([
                    ('id', '7d9b54f1-0006-42d9-98a9-f5f1b4f37130'),
                    ('description', 'python'),
                    ...
                ('ranking', 10),
                ('description', 'Primer on Python Decorators'),
                ...

        Serialized JSON:
        {
            "4fa56608-b6a0-492a-9989-7d3e46c1b581": {
                "id": "4fa56608-b6a0-492a-9989-7d3e46c1b581",
                "category": {
                    "id": "a28337ed-1ecf-4bde-af7c-905456ebc5eb",
                    "description": "raspberry_pi",
                    ...
                },
                "ranking": 10,
                "description": "Extending the life of your Raspberry PI SD Card",
                ...
          },
          ...
    """
    serializer = LinkSerializer(queryset, many=True)
    #data = serializer.data
    # For faster lookup, transform the list of results into a dictionary, using row id as key
    data = {row['id']: row for row in serializer.data}
    return mark_safe(JSONRenderer().render(data).decode())