【问题标题】:use json data in django template在 django 模板中使用 json 数据
【发布时间】:2020-08-03 10:05:16
【问题描述】:

我有一个模型,它有一个类,它由许多其他使用 OneToOneField 的类组成。 我的最终目标是能够以抽象的方式(不使用字段名称)循环数据结构并使用模板标签将内容输出到我的模板。我想为我的模板提供嵌套json 格式的数据,并直接在我的模板中使用模板标签解析 json。我已经使用了 Django rest 框架。以下是我的代码库的通用示例:


models.py--------------------------------------

from django.db import models
from rest_framework import serializers


class Class1(models.Model):
    class_1_field_1 = models.CharField()
    class_1_field_2 = models.CharField()


class Class2(models.Model):
    class_2_field_1 = models.CharField()
    class_2_field_2 = models.CharField()


class MainClass(models.Model):
    field_1 = models.CharField()
    field_2 = models.IntegerField()
    field_3 = models.DateTimeField()

    class_1 = models.OneToOneField(Class1, on_delete=models.CASCADE,)
    class_2 = models.OneToOneField(Class2, on_delete=models.CASCADE,)


class Class1Serializer(serializers.ModelSerializer):
    class Meta:
        model = Class1
        fields = ('class_1_field_1', 'class_1_field_2')


class Class2Serializer(serializers.ModelSerializer):
    class Meta:
        model = Class2
        fields = ('class_2_field_1', 'class_2_field_2')


class MainClassSerializer(serializers.ModelSerializer):
    class_1= Class1Serializer()
    class_2= Class2Serializer()

    class Meta:
        model = MainClass
        fields = ('field1', 'field2', 'field3', 'class_1', 'class_2')


views.py-------------------------------------

from django.views.generic import ListView
from rest_framework.renderers import JSONRenderer
from MyApp.models import MainClass, MainClassSerializer


MainClassListView(ListView):
    context_object_name = 'mainclasses'
    model = MainClass
    serializer_class = MainClassSerializer

    def get_queryset(self):
        object_list = MainClass.objects.filter(user__in=[self.request.user])
        return object_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        serializer = MainClassSerializer(MainClass.objects.filter(user__in=[self.request.user]), many=True)
        context['data'] = JSONRenderer().render(serializer.data)
        return context

    def dispatch(self, request, *args, **kwargs):
        return super(MainClassListView, self).dispatch(request, *args, **kwargs)


index.html----------------------------------------------------

...

{{data}}

...

json output-------------------------------------------------------

b'[{
   "field_1": "Some String",
   "field_2": 100,
   "field_3": "2020-04-20T02:34:27.912451Z",
   "class_1": {
      "class_1_field_1": "str_1",
      "class_1_field_2": "str_2"
   },
   "class_2": {
      "class_2_field_1": "str_3",
      "class_2_field_2": "str_4"
   }
}]'

{{data}} 标记显示具有以下格式的字符串(见上文):b'[valid_json_is_displayed_here]',其中valid_json_is_displayed_here 是格式正确的 json 结构,其中包括来自 OneToOneField 关系的嵌套数据。

我想直接在我的模板中解析模板标签中返回的 json 输出中的各个值,包括一对一的关系数据。这在 Django 中是否可行,我该如何实现?我觉得它应该很简单,我错过了什么?

谢谢。

【问题讨论】:

  • 或者,您可以简单地将MainClass 实例传递给模板,并在模板中访问mainClassInstance.class_1.class_1_field1 等字段。更简单、更干净的代码。

标签: django django-models django-rest-framework django-templates


【解决方案1】:

Django template can parse dict 带点符号。

因此,如果您将dict 添加到context,它将使解析变得非常容易。

import json

def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        serializer = MainClassSerializer(MainClass.objects.filter(user__in=[self.request.user]), many=True)
        context['data'] = json.loads(JSONRenderer().render(serializer.data))
        return context

在模板中:

{% for d in data %}
    {{ d.field1}}
    {{ d.class_1.class_1_field_1}}
{% endfor %}

但是,您可以简单地将MainClass 实例传递给模板,然后访问模板中的mainClassInstance.class_1.class_1_field1 等字段,而不是这样做。

def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['data'] = MainClass.objects.filter(user__in=[self.request.user])
        return context

在模板中:

{% for d in data %}
    {{ d.field1}}
    {{ d.class_1.class_1_field_1}}
{% endfor %}

【讨论】:

  • 谢谢你,@narendra-choudhary。我面临的一个问题是以非常通用的方式遍历所有返回的数据,并使用标签将其输出到 UI。我可以看到我没有在我的问题中说清楚。您是否知道我如何使用您提出的“模型”解决方案来实现这一目标?我的印象是使用 json 结构更容易实现。你对此有意见吗?我将无法按名称访问字段,只能通过“抽象”循环({% for x in data %},或以某种方式通过索引等)。
  • 您将能够按名称访问字段。 data 解析为 QuerySetMainClass 模型。 QuerySets 是可迭代的,因此 dfor 循环中解析为 MainClass 对象。然后,您可以使用. 表示法访问此对象的所有字段(包括OneToOneFields)。
  • 是的,这是真的——你是对的。 :) 我的意思是我有很多数据,实际上,我不想将每个字段名称都输入到我的页面中以显示数据。我可以通过这种方式获取数据,这是绝对正确的,但出于我的目的,我需要一个更抽象的解决方案。抱歉,我对此不太清楚。感谢您继续与我一起解决这个问题。 :)
  • 您想要像 {{ d.class_1 }} 这样的东西来呈现相关 Class1 实例的 JSON 表示?这将避免在模板中列出Class1 的所有字段。
  • 有了你建议的改变,我现在从{{data}}返回:[{ "field_1": "Some String", "field_2": 100, "field_3": "2020-04-20T02:34:27.912451Z", "class_1": { "class_1_field_1": "str_1", "class_1_field_2": "str_2" }, "class_2": { "class_2_field_1": "str_3", "class_2_field_2": "str_4" } }];我尝试使用{% for k, v in data.items %},但没有任何结果——实际上没有返回任何内容。如何从这个结构中获取数据?看起来好像我有一个带有单个值的 dict,它是一个 json 结构......
猜你喜欢
  • 2018-10-02
  • 2011-09-11
  • 2014-11-12
  • 2020-11-04
  • 2017-08-13
  • 1970-01-01
  • 2021-09-29
  • 2021-06-18
  • 1970-01-01
相关资源
最近更新 更多