Django w / sqlite3 CharField在特殊角色上崩溃:“Rüppell's Vulture”

时间:2016-06-17 15:03:38

标签: python django csv unicode sqlite

Django verision 1.9,DB backend:sqlite3。

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

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

这里有错误:

  

ProgrammingError:除非使用a,否则不得使用8位字节串   text_factory,可以解释8位字节串(如text_factory =   STR)。强烈建议您只需切换即可   应用于Unicode字符串。

我正在阅读有关unicode字符串的Django's documentation。这开始就像这样:

  

Django原生支持各处的Unicode数据。提供你的   数据库可以以某种方式存储数据,您可以安全地传递   Unicode字符串到模板,模型和数据库。

同时查询information关于此字符:ü,它的表示形式是unicode和utf-8。

将此字符串保存到数据库的方法非常简单,我只是使用csv.reader解析CSV文件:

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

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

更新

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

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

1 个答案:

答案 0 :(得分:2)

Django CharField是一种面向字符的格式。您需要传递Unicode字符串。

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

要从字节到字符,您必须知道在导出CSV文件时将原始字符转换为字节时使用的编码。理想情况下,这将是UTF-8,但如果文件来自Excel,它可能不会。也许它是Windows-1252(西欧安装的'ANSI'代码页)。也许它是别的东西。

(当你只有ASCII字节(字节0-127)时,Django / Python 2可以让你将字节串写入Unicode属性,因为它们在批量编码中具有相同的映射.ASCII是'最佳猜测'尽我所能,但它不可靠,如果你尝试,Python 3更喜欢引发错误。)

所以:

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

或者,一次解码整行:

row = [s.decode('windows-1252') for s in row]