2012-01-05 38 views
0

我的線沿線的一個觀點:的Django如何最好地解決Unicode的錯誤

def export(request, exportCSV): 
    if exportCSV: 
    ... 
    # get a list of results named list 
    ... 
    response = HttpResponse(mimetype='text/csv') 
    response['Content-Disposition'] = 'attachment; filename=myfile.csv' 
    writer = csv.writer(response) 

    writer.writerow(['firstfield', 'secondfield', ... ,]) 
    for item in list: 
     writer.writerow([item.firstfield, item.secondfield, ... ,]) 
    return response 

的問題是,某些字段包含西班牙語文本等領域引發以下錯誤:

'ascii' codec can't encode character u'\xe9' in position 3: ordinal not in range(128) 

現在,如果我追加.encode('utf8)至得罪領域,一切都很好:

... 
for item in list: 
    writer.writerow([item.firstfield.encode('utf8'), item.secondfield.encode('utf8'), ... ,]) 

然而,將此分配給每個字段明顯違反了DRY。另外,並非每個字段都接受這種編碼。如果我追加到一些領域我產生這個錯誤:

'int' object has no attribute 'encode' 

或:

'NoneType' object has no attribute 'encode' 

所以,我怎麼能與這第一個錯誤,同時確保字段不產生第二類錯誤的最好的交易?我應該甚至在視圖層面處理這個問題,還是可以在模型中處理?

+1

http://docs.python.org/library/csv.html#examples,有一個unicode_csv_reader的例子。你也可以捕獲UnicodeDecodeError(或者你看到的w/e錯誤)並且適當地對文本字段進行編碼。 – dm03514 2012-01-05 21:09:02

+0

hmm。我嘗試過使用UnicodeWriter類,但仍然遇到相同的錯誤。 – 2012-01-06 00:30:25

回答

2

smart_str有外觀和這裏的其他轉換功能:https://docs.djangoproject.com/en/dev/ref/unicode/#conversion-functions

保持乾燥,你可以使用它像這樣...

my_fields = ['firstfield', 'secondfield', 'thirdfield'] 

for item in list: 
    writer.writerow([smart_str(getattr(item, x)) for x in my_fields]) 

編輯 FK關係

嘗試像(未經測試)...

def get_field(obj, field): 
    value = obj 

    for f in field.split('.'): 
     value = getattr(value, f) 

    return value 

my_fields = ['firstfield.firstsubfield', 'secondfield.sub.subsub', 'thirdfield'] 

for item in list: 
    writer.writerow([smart_str(get_field(item, x)) for x in my_fields]) 

get_field方法應該適用於任何關係深度。

+0

這看起來很有希望。但是,我提交的查詢涉及多個連接。如何在'item.firstfield.firstsubfield'上使用'getattr'? – 2012-01-06 00:45:15

+0

請參閱編輯。添加了處理FK關係的方法。 – ejb 2012-01-06 02:08:49

+0

太棒了!謝謝。在我的情況下,'firstfield'對於所有查詢都很常見,我實際上可以避開:'fields_list])'中的''writer.writerow([smart_str(get_field(firstfield,x))。而'smart_str'絕對是處理所有字段的方式,無論是西班牙文字還是None或Int。 – 2012-01-06 15:45:17

0

所以,爲了完整。這裏是我的工作代碼:

# get_field function 
def get_field(obj, field): 
    value = obj 
    for f in field.split('.'): 
     value = getattr(value, f) 
    return value 

def csv(request, exportCSV) 
    ... 
    if exportCSV: 
     response = HttpResponse(mimetype='text/csv') 
     response['Content-Disposition'] = 'attachment; filename=myfile.csv' 
     writer = csv.writer(response) 
     # write headings     
     writer.writerow([ 
      'Verbose Heading FirstField', 
      'Verbose Heading ScondField', 
     ]) 
     # create list of fields as objects 
     fields_list = [ 
      'subfield1.subsubfield1.subsubsubfield1', 
      'subfield1.subfield2', 
     ] 
     for item in results_list: 
      writer.writerow([smart_str(get_field(item, x)) for x in fields_list])