首页 > 解决方案 > Django的json问题:'tuple'对象没有属性'_meta'

问题描述

我正在尝试将数据从查询集导出为不同的文件格式,但我遇到了 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)

标签: pythonjsondjango

解决方案


请不要自己做序列化: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

推荐阅读