Включение данных сериализатора django rest с помощью шаблона-тега Django `json_script`
Я использую Django Camel Case для перехода от pythons snake_case в бэкенде к camelCase во фронтэнде, чтобы ключи данных соответствовали обычному синтаксису JavaScript.
Это отлично работает для вызовов AJAX, возвращающих JSON.
Однако часто я хочу вставить некоторый JSON в HTML-шаблон с помощью стандартной функции Django 'json_script`. Я не хочу использовать какой-либо другой JSON strinfier, потому что тогда он не будет безопасно экранирован.
Проблема в том, что когда я вставляю JSON в HTML, он не camelCased:
Пример
# --- models.py ---
from django.db import models
class Foo(models.Model):
last_name = models.CharField(max_length=250, unique=True)
# --- serializers.py ---
from rest_framework import serializers
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = Foo
fields = ('id', 'last_name')
# --- views.py ---
from django.views import generic
from . import models
class IndexView(generic.ListView):
template_name = f"myapp/index.html"
model = Foo
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['serializer'] = serializers.FooSerializer(self.object_list, many=True)
return context
Затем в шаблоне:
{{ serializer.data|json_script:"FOO_DATA" }}
<script type="module">
const foos = JSON.parse(document.getElementById('FOO_DATA').textContent);
console.log(foos)
</script>
Но, к сожалению, это приведет к чему-то вроде:
[{ id: 1, last_name: 'Smith'}, { id: 2, last_name: 'Kent'}]
Но я требую, чтобы last_name
был в верблюжьей оболочке:
[{ id: 1, lastName: 'Smith'}, { id: 2, lastName: 'Kent'}]
Как можно безопасно внедрить данные JSON и преобразовать их в camelCase?
В итоге я создал пользовательский фильтр шаблонов, не вижу более простого способа:
from django import template
from django.utils import html
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter()
def camelize_json_script(data, element_id):
"""
Based on: django.utils.html.json_script
Escape all the HTML/XML special characters with their unicode escapes, so
value is safe to be output anywhere except for inside a tag attribute. Wrap
the escaped JSON in a script tag.
"""
from djangorestframework_camel_case.render import CamelCaseJSONRenderer
json_str = CamelCaseJSONRenderer().render(data).decode().translate(html._json_script_escapes)
return html.format_html(
'<script id="{}" type="application/json">{}</script>', element_id, mark_safe(json_str)
)
Если вы хотите автоматически загрузить этот тег шаблона, вы можете сделать это как показано здесь.