与json的Django问题:'tuple'对象没有属性'_meta'

问题描述 投票:1回答:4

我正在尝试将查询集中的数据导出到不同的文件格式,我遇到了json格式的问题。

这是我的一小段代码:

from django.core import serializers

def export_categories_json(request):

    with open("categories.json", "w") as out:
        data = serializers.serialize("json", Category.objects.all().values_list('id', 'name'))
        out.write(data)

然后,我在模板中设置了一个调用此函数的按钮,并应下载json文件。但我有这个问题:

Traceback:

File "/home/val/.pyenv/versions/Publication3.6.2/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/val/.pyenv/versions/Publication3.6.2/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/val/.pyenv/versions/Publication3.6.2/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/val/Bureau/Projets/Publication/publication/src/web/views/exports.py" in export_categories_json
  276.         data = serializers.serialize("json", Category.objects.all().values_list('id', 'name'))

File "/home/val/.pyenv/versions/Publication3.6.2/lib/python3.6/site-packages/django/core/serializers/__init__.py" in serialize
  129.     s.serialize(queryset, **options)

File "/home/val/.pyenv/versions/Publication3.6.2/lib/python3.6/site-packages/django/core/serializers/base.py" in serialize
  84.             concrete_model = obj._meta.concrete_model

Exception Type: AttributeError at /Category/json
Exception Value: 'tuple' object has no attribute '_meta'

我的代码有问题吗?我无法向json文件发送查询集?

编辑:

我写了这个并且它有效,但json显示在我的模板中。我如何将这个导出到json文件?

def export_categories_json(request):
    from django.http import JsonResponse

    data = list(Category.objects.values())
    return JsonResponse(data, safe=False)
python json django
4个回答
2
投票

请不要自己进行序列化:Django有一些内置的序列化功能,你可以子类化序列化程序来改变它的行为。

您的视图也不会返回HTTP响应,但这是它应该满足的合同(它应该返回HTTP响应,否则应该引发一些错误)。

相反,您将内容写入文件,但写入文件通常不是一个好主意(除非您希望文件大小很大,在这种情况下您可以使用临时文件)。通过使用文件,您创建竞争条件,黑客也可能旨在“注入”不同的文件名,从而覆盖某些文件以运行任意代码,或更改凭据,最后服务器可能具有某些权限使其无法写入文件(目录的权限)。

Django允许您查看HTTP响应作为流对象,可以将内容写入,例如:

from django.http import HttpResponse
from django.core import serializers

def export_categories_json(request):
    response = new HttpResponse(content_type='application/json')
    response['Content-Disposition'] = 'attachment;filename=categories.json'
    serializers.serialize(
        'json',
        Category.objects.all(),
        fields=['name'],
        stream=response
    )
    return response

0
投票

Django的序列化适用于模型,但您使用的是.values_list(),它返回普通的Python lists。

在您的具体情况下,您可以简单地使用内置的json模块:

import json

def export_categories_json(request):

    with open("categories.json", "w") as out:
        values = list(Category.objects.all().values_list('id', 'name'))
        json.dump(values, out)

0
投票

除了queryset对象之外的django序列化,

 Category.objects.all().values_list('id', 'name')

这将返回元组,你可以用下面替换

data = list(Category.objects.all().values('id', 'name'))
with open("file.json", "w+") as file:
      file.write(data)

0
投票

如果要将某些内容的json表示写入文件,请使用json.dump

import json

from django.shortcuts import redirect

def export_to_json(request):
    with open('export.json', 'w') as f:
       json.dump(list(Category.objects.all().values_list('id', 'name')), f)
    return redirect('/')
© www.soinside.com 2019 - 2024. All rights reserved.