以django

时间:2015-05-17 15:36:52

标签: django csv utf-8

我正在尝试输出用户可以使用excel打开的CSV文件。我用UTF-8编写了所有字符串,但是当我用excel打开文件时,我看到了jibrish。只有在使用BOM将文件转换为UTF-8(在Windows上使用notepad ++)之后,我才能正确显示内容。

我正在遵循docs

中的这种模式
def render_to_csv(self, request, qs): 
  response = HttpResponse(content_type='text/csv')
  response['Content-Disposition'] = 'attachment; filename="test.csv"'

  writer = csv.writer(response, delimiter=',')

  for row in qs.values_list(*self.fields_to_export):
    writer.writerow([unicode(v).encode('utf-8') if v is not None else '' for v in row])

  return response

BOM在哪里适用于所有这些?

顺便说一句,SO上有similar questions但很遗憾没有人回答。

修改

在@Alastair McCormack的基础上,我最终明确地在文件的开头添加了BOM字符。唯一的区别是我使用了编解码器包而不是硬编码字节。感觉很尴尬,但做的伎俩!

import codecs

def render_to_csv(self, request, qs): 
  ... 
  response.write(codecs.BOM_UTF8)
  ...
  return response

4 个答案:

答案 0 :(得分:5)

在编写数据之前,将UTF-8 BOM添加到响应对象:

def render_to_csv(self, request, qs): 
  response = HttpResponse(content_type='text/csv')
  response['Content-Disposition'] = 'attachment; filename="test.csv"'

  # BOM      
  response.write("\xEF\xBB\xBF")

  writer = csv.writer(response, delimiter=',')
  …

答案 1 :(得分:2)

StreamingHttpResponse csv添加UTF-8 BOM或\xEF\xBB\xBF

从官方documents修改

import csv
import codecs

from django.utils.six.moves import range
from django.http import StreamingHttpResponse


class Echo(object):
    def write(self, value):
        return value


def iter_csv(rows, pseudo_buffer):
    yield pseudo_buffer.write(codecs.BOM_UTF8)
    writer = csv.writer(pseudo_buffer)
    for row in rows:
        yield writer.writerow(row)


def some_streaming_csv_view(request):
    rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
    response = StreamingHttpResponse(iter_csv(rows), Echo()), content_type="text/csv")
    return response

答案 2 :(得分:1)

给出的答案很好,但我想提示如何通过只更改一行来使official examples from the Django docs在流的开头使用UTF-8 BOM字节序列:

import itertools
import codecs 

streaming_content = itertools.chain([codecs.BOM_UTF8], (writer.writerow(row) for row in rows))
response = StreamingHttpResponse(streaming_content, content_type="text/csv")

答案 3 :(得分:-1)

就我而言,作为HTTP响应返回时,第一个BOM_UTF8字符会自动删除。所以我不得不手动添加两个BOM_UTF8字符。

response.write(codecs.BOM_UTF8)
response.write(codecs.BOM_UTF8)
response.write(encoded_csv_content)

我不知道原因,但也许会帮助某人,或者知道原因的人可以在评论中进行解释。