Django 将带有外键的查询集转换为 JSON

Posted

技术标签:

【中文标题】Django 将带有外键的查询集转换为 JSON【英文标题】:Django Converting Queryset with Foreign Keys to JSON 【发布时间】:2019-07-14 10:34:36 【问题描述】:

我正在尝试将 JSON 对象传递给我的模板。我有一些无法修改的复杂关系。基于操作系统 帖子我尝试了不同的东西。我认为让我亲近的是:

我创建了一个看起来像这样的 .values() 查询集

    def my_queryset():
         results=TodaysResults.objects.values('id','foreignModel1__name',
        'foreignModel1__ForeignModel2__title')
        print (myquery_set)

my_queryset 为我提供了我需要的所有值。所以我尝试使用以下方法对其进行转换。 1)

def make_querydict():
    results=TodaysResults.objects.values('id','foreignModel1__name',
    'foreignModel1__ForeignModel2__title')
    json_results=json.dumps(list(results,cls=DjangoJSONEncoder))
    print (json_results)

我收到以下错误:

"TypeError: list() 没有关键字参数"

2) 我也试过这个:

def serialize():
        fields = ['id','foreignModel1__name','foreignModel1__ForeignModel2__title']
        qs = TodaysResults.objects.all()
        json_data = serializers.serialize('json',qs,fields=fields) 
        print(json_data)

但是当我打印 json_data 时,只显示 id 而不是外部值。

3)基于一些相同的答案like this(从2012年开始)我试过了:

    def for_JSON_response():
    response=JsonResponse(dict(results_info=list(TodaysResultslts.objects.values('id','foreignModel1__name',
    'foreignModel1__ForeignModel2__title')
    print(response)

我没有收到任何错误,但它没有打印任何内容。所以,我假设什么都没发生。

4) 基于this 我试过了:

 def my_queryset():
     results=TodaysResults.objects.values('id','foreignModel1__name',
    'foreignModel1__ForeignModel2__title')
    print (JsonResponse(results, safe=False))

我明白了:

TypeError:QuerySet 类型的对象不是 JSON 可序列化的

我试过了:

  def my_queryset():
     results=TodaysResults.objects.values('id','foreignModel1__name',
    'foreignModel1__ForeignModel2__title')
     results_json = serializers.serialize('json',results)

我得到了:

AttributeError: 'dict' 对象没有属性 '_meta'

我一直在四处寻找,有些回复看起来已经过时了。我上面的尝试是我认为最接近转换 valuesqueryset 到 json 或将我需要的值放入 JSON。有没有办法像我在 my_queryset 中那样进行链式查询并将其转换为 JSON?

模型.Py 为这个例子简化了

class TodaysResults(models.Model):
place = models.CharField(max_length=255)
ForeignModel1 = models.ForeignKey(ForeignModel,related_name='m1')

class ForeignModel(models.Model):
name = Models.CharField(max_length=255)
ForeignModel2 = models.ManyToManyField(M2M, related_name='m2')

class M2M(models.Model):
title = Models.CharField(max_length=255)

【问题讨论】:

你使用django-restframework的序列化器link 我从未使用过 django-restframework。并不是我不接受它。只是 .values() my_queryset 已经拥有我需要的所有字段,我什至可以使用注释 F 将“foreignModel1__ForeignModel2__title”重命名为标题。DjangoRestFramework 可以用于序列化查询集吗? 是的,可以。您可以安全地使用它。它将帮助您以最低的负担做很多事情。 好的。我正在阅读您提供的链接,我看到了一些名为“serpy”的东西?我想我正在尝试找到可以使用查询集的东西?我关心的是外键和多对多字段。 我想建议阅读有关 ModelSerializer 的信息,我将发布一个答案,django-rest-framework 序列化程序如何解决您的问题。 【参考方案1】:

这里我们有三个模型TodaysResultsForeignModelMModel,我猜MModelmanyTomanyForeignModel 的关系。我提出了两种可能的方式,我们如何从TodaysResults 序列化程序中获取所有信息。

可能的解决方案一

from rest_framework import serializers

class MModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MModel
        fields = ('title',)

class ForeignModelSerializer(serializers.ModelSerializer):
    foreignModel2 = MModelSerializer(many=True) # as it is many to many field
    class Meta:
        model = ForeignModel
        fields = ('name', 'foreignModel2',)

class TodaysResultsSerializer(serializers.ModelSerializer):
    foreignModel1 = ForeignModelSerializer()
    class Meta:
        model = TodaysResults
        fields = ('place', 'foreignModel1')

现在传递您的 TodaysResults 查询集 TodaysResultsSerializer 并从 serializer.data 获取您的序列化数据。

可能的解决方案二

即使我们可以用一个序列化来做到这一点,因为并非所有字段都是必需的。

class TodaysResultsSerializer(serializers.ModelSerializer):
    class Meta:
        model = TodaysResults
        fields = ('place', 'foreignModel1__name', 'foreignModel1__foreignModel2__title')

虽然我不完全确定,但这也应该有效。

【讨论】:

您需要通过TodaysResults.objects.all() 的queryest 以获得第一个解决方案,在那里您将获得您想要的字段。第二个你的结果应该有效。

以上是关于Django 将带有外键的查询集转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将 Django 模型查询集转换为模板中的 json 或 json 字符串?

在 Django 视图中获取多项选择查询集并保存

外键的过滤查询集[关闭]

Django 多注解返回错误结果

将查询集传递给 django 内联表单中的外键字段

在 ListView 中过滤具有外键值的查询集