2016-06-17 22 views
0

Django verision 1.9,DB后端:sqlite3。Django w/sqlite3 CharField在特殊字符上崩溃:“Rüppell's Vulture”

我很难搞清楚如何处理这个错误。我将主鸟物种列表(available here)导入一组Django模型。我的导入进行得很顺利,但是当我试图将该值保存到模型中时,导致崩溃:Rüppell's Vulture。目标字段的定义如下:

species_english = models.CharField(max_length=100, default=None, blank=True, null=True) 

这里是有错误:

ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.

我是通过Django's documentation阅读unicode字符串。其精美开始了这样的:

Django natively supports Unicode data everywhere. Providing your database can somehow store the data, you can safely pass around Unicode strings to templates, models and the database.

而且查找information这个角色:ü,它表示是Unicode和UTF-8。

保存这个字符串到数据库的方法是非常直接的,我只是解析使用csv.reader CSV文件:

new_species = Species(genus=new_genus, species=row[4], species_english=row[7]) 

当错误抛出字符串包含在row[7]。我错过了为什么数据库不允许这个角色?

UPDATE

这里是整个脚本的导入数据内容:

import csv 
from birds.models import SpeciesFile, Order, Family, Genus, Species, Subspecies 

csv_file = str(SpeciesFile.objects.all()[0].species_list) 

#COLUMNS 
#0 - Order 
#1 - Family Scientific 
#2 - Family (English) 
#3 - Genus 
#4 - Species 
#5 - SubSpecies 


with open("birds/media/"+csv_file.split('/')[1], 'rU') as c: 
    Order.objects.all().delete() 
    Family.objects.all().delete() 
    Genus.objects.all().delete() 
    Species.objects.all().delete() 
    Subspecies.objects.all().delete() 
    reader = csv.reader(c, delimiter=';', quotechar='"') 
    ini_rows = 4 
    for row in reader: 
     if ini_rows > 0: 
      ini_rows -= 1 
      continue 
     if row[0]: 
      new_order = Order(order=row[0]) 
      new_order.save() 
     elif row[1]: 
      new_fam = Family(order = new_order, family_scientific=row[1], family_english=row[2]) 
      new_fam.save() 
     elif row[3]: 
      new_genus = Genus(family = new_fam, genus=row[3]) 
      new_genus.save() 
     elif row[4]: 
      print row[4] 
      new_species = Species(genus=new_genus, species=row[4], species_english=row[7]) 
      new_species.save() 
     elif row[5]: 
      print row[5] 
      new_subspecies = Subspecies(species=new_species, subspecies=row[5]) 
      new_subspecies.save() 

这里是models.py文件定义:

from __future__ import unicode_literals 

from django.db import models 

class SpeciesFile(models.Model): 
    species_list = models.FileField() 

class Order(models.Model): 
    order = models.CharField(max_length=100) 

    def __str__(self): 
     return self.order 

class Family(models.Model): 
    order = models.ForeignKey(Order) 
    family_scientific = models.CharField(max_length=100) 
    family_english = models.CharField(max_length=100) 

    def __str__(self): 
     return self.family_english+" "+self.family_scientific 

class Genus(models.Model): 
    family = models.ForeignKey(Family) 
    genus = models.CharField(max_length=100) 

    def __str__(self): 
     return self.genus 

class Species(models.Model): 
    genus = models.ForeignKey(Genus, default=None) 
    species = models.CharField(max_length=100, default=None) 
    species_english = models.CharField(max_length=100, default=None, blank=True, null=True) 

    def __str__(self): 
     return self.species+" "+self.species_english 

class Subspecies(models.Model): 
    species = models.ForeignKey(Species) 
    subspecies = models.CharField(max_length=100) 

    def __str__(self): 
     return self.subspecies 
+0

请稍等在该代码的上下文中,包括正在阅读CSV的部分。 –

+0

@DanielRoseman - 谢谢,我包括导入脚本和models.py内容。 –

+0

这是Python 3吗? –

回答

2

Django的CharField是面向字符的格式。你需要传递它的Unicode字符串。

CSV是一种面向字节的格式。当您从CSV文件中读取数据时,您将获得字节字符串。

要从字节获取字符,您必须知道在导出CSV文件时原始字符转换为字节时使用了什么编码。理想情况下,这将是UTF-8,但是如果文件已经从Excel中出来,它可能不会。也许它是Windows-1252(西欧安装的'ANSI'代码页)。也许这是别的。 (Django/Python 2允许你在只有ASCII字节的情况下将字节串写入Unicode属性(字节0-127),因为它们在很多编码中具有相同的映射关系。ASCII是'最好的在待办事项我的意思猜,但它是不可靠和Python 3喜欢,如果你尝试引发错误)

这样:

new_order = Order(order=row[0].decode('windows-1252')) 

,或者整个行一次解码:

+0

你的'windows-1252'编码不起作用,当然你的编码问题是正确的。我结束了与谷歌文档打开xls文件,然后从那里下载csv。它在不指定编码的情况下处理新文件。我的Mac上有中文版的excel,所以它一定是一些奇怪的编码。 –