Django将日期时间转换为可序列化的JSON字符串

2 投票
1 回答
2922 浏览
提问于 2025-04-18 06:13

在处理我的记录排序时,我发现如果模型中的日期时间字段有日期,搜索就容易崩溃。我需要把这个日期字段(date_produced)保存到会话中,以便后面可以导出成CSV文件。但我不太确定在这个过程中哪里可以把这个字段的值转换成字符串。

错误信息是:“datetime.date(2014, 5, 6) 不能被转换成 JSON 格式”。

这是我的 views.py 文件:

def sort(request, project_id=1):
    thisuser = request.user
    if Project.objects.filter(id=project_id).exists():
        project = Project.objects.filter(id=project_id).order_by('pubdate')[0]
    else:
        project = None

    if Project.objects.filter(Q(created_by=thisuser) | Q(project_access__access_list=thisuser), id=project_id).exists():
        permission = 1
    else:
        permission = None

    if Asset.objects.filter(project__id=project_id, unique_id=1):
        assets = 1
    else:
        assets = None


    if request.POST:
        if Project.objects.filter(Q(created_by=thisuser) | Q(project_access__access_list=thisuser), id=project_id).exists():
            if request.POST.get('date_start') and request.POST.get('date_end'):
                date_start  = datetime.strptime(request.POST['date_start'], '%m/%d/%Y')
                date_end    = datetime.strptime(request.POST['date_end'], '%m/%d/%Y')
                q_date      = Q(date_produced__range=[date_start, date_end])
            else:
                q_date      = Q(date_produced__isnull=False) | Q(date_produced__isnull=True)

            text_fields = {
                'asset_type': request.POST.get('asset_type'),
                'description': request.POST.get('description'),
                'master_status': request.POST.get('master_status'),
                'location': request.POST.get('location'),
                'file_location': request.POST.get('file_location'),
                'footage_format': request.POST.get('footage_format'),
                'footage_region': request.POST.get('footage_region'),
                'footage_type': request.POST.get('footage_type'),
                'footage_fps': request.POST.get('footage_fps'),
                'footage_url': request.POST.get('footage_url'),
                'stills_credit': request.POST.get('stills_credit'),
                'stills_url': request.POST.get('stills_url'),
                'music_format': request.POST.get('music_format'),
                'music_credit': request.POST.get('music_credit'),
                'music_url': request.POST.get('music_url'),
                'license_type': request.POST.get('license_type'),
                'source': request.POST.get('source'),
                'source_contact': request.POST.get('source_contact'),
                'source_email': request.POST.get('source_email'),
                'source_id': request.POST.get('source_id'),
                'source_phone': request.POST.get('source_phone'),
                'source_fax': request.POST.get('source_fax'),
                'source_address': request.POST.get('source_address'),
                'credit_language': request.POST.get('source_language'),
                'cost': request.POST.get('cost'),
                'cost_model': request.POST.get('cost_model'),
                'total_cost': request.POST.get('total_cost'),
                'notes': request.POST.get('notes')
                }

            boolean_fields = {
                'used_in_film': request.POST.get('used_in_film'),
                'footage_blackandwhite': request.POST.get('footage_blackandwhite'),
                'footage_color': request.POST.get('footage_color'),
                'footage_sepia': request.POST.get('footage_sepia'),
                'stills_blackandwhite': request.POST.get('stills_blackandwhite'),
                'stills_color': request.POST.get('stills_color'),
                'stills_sepia': request.POST.get('stills_sepia'),
                'license_obtained': request.POST.get('license_obtained')
                }

            q_objects = Q()

            for field, value in text_fields.iteritems():
                if value:
                    q_objects = Q(**{field+'__contains': value})

            q_boolean = Q()

            for field, value in boolean_fields.iteritems():
                if value:
                    q_boolean |= Q(**{field: True})

            query_results = Asset.objects.values('unique_id', 'asset_type', 'description', 'used_in_film', 'master_status', 
                str('date_produced'), 'location', 'file_location', 'footage', 'footage_format', 'footage_region', 'footage_type', 
                'footage_fps', 'footage_url', 'footage_blackandwhite', 'footage_color', 'footage_sepia', 'stills', 'stills_credit', 
                'stills_url', 'stills_blackandwhite', 'stills_color', 'stills_sepia', 'music', 'music_format', 'music_credit', 
                'music_url', 'license_obtained', 'license_type', 'source', 'source_contact', 'source_email', 'source_id', 
                'source_phone', 'source_fax', 'source_address', 'credit_language', 'total_use', 'timecode_total', 'windowdub_total', 
                'cost', 'cost_model', 'total_cost', 'notes').filter(q_date, q_objects, q_boolean, project__id=project_id)

for instance in query_results:
                instance['date_produced'] = instance['date_produced'].strftime('%Y-%m-%d')

            request.session['query_results'] = list(query_results)

            args = {'query_results': query_results, 'thisuser': thisuser, 'project': project, 'assets': assets, 'permission': permission}
            args.update(csrf(request))

            args['query_results'] = query_results

            return render_to_response('sort_results.html', args)
        else:
            return render_to_response('sort_results.html', args)

    else:

        args = {'thisuser': thisuser, 'project': project, 'assets': assets, 'permission': permission}
        args.update(csrf(request))

        return render_to_response('sort.html', args)

我在 Asset.objects.values(str('date_produced')).filter 函数中使用了 str('date_produced'),但这似乎并没有把它转换成字符串。我还在我的查询结果上运行了一个列表,以便让它可以被转换成 JSON 格式,但这也没有成功。

有没有什么想法?

完整的错误追踪信息:

Traceback (most recent call last):
  File "/webapps/filmeditdb/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 201, in get_response
    response = middleware_method(request, response)
  File "/webapps/filmeditdb/local/lib/python2.7/site-packages/django/contrib/sessions/middleware.py", line 38, in process_response
    request.session.save()
  File "/webapps/filmeditdb/local/lib/python2.7/site-packages/django/contrib/sessions/backends/db.py", line 57, in save
    session_data=self.encode(self._get_session(no_load=must_create)),
  File "/webapps/filmeditdb/local/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py", line 87, in encode
    serialized = self.serializer().dumps(session_dict)
  File "/webapps/filmeditdb/local/lib/python2.7/site-packages/django/core/signing.py", line 88, in dumps
    return json.dumps(obj, separators=(',', ':')).encode('latin-1')
  File "/usr/lib/python2.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: datetime.date(2014, 5, 6) is not JSON serializable

现在问题解决了,我找到的有效代码是:

for instance in query_results:
instance['date_produced'] = instance['date_produced'].strftime('%Y-%m-%d')

1 个回答

1

在把日期传给JSON响应之前,你需要先对日期进行处理:

json.dump(your_date.strftime('%Y-%m-%dT%H:%M:%S'))

https://docs.python.org/2/library/time.html#time.strftime

for instance in query_results:
    instance.date_produced = json.dump(instance.date_produced.strftime('%Y-%m-%dT%H:%M:%S'))

撰写回答