【问题标题】:Django w/ sqlite3 CharField crashing on special character: "Rüppell's Vulture"带有 sqlite3 CharField 的 Django 在特殊字符上崩溃:“Rüppell 的秃鹰”
【发布时间】:2016-10-19 11:36:30
【问题描述】:

Django 1.9 版,数据库后端:sqlite3。

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

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

这里有错误:

ProgrammingError: 你不能使用 8 位字节串,除非你使用 text_factory 可以解释 8 位字节串(如 text_factory = 字符串)。强烈建议您直接切换您的 应用于 Unicode 字符串。

我正在通过Django's documentation 阅读有关 unicode 字符串的信息。开头很漂亮:

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

【问题讨论】:

  • 请显示该代码的上下文,包括读取 CSV 的部分。
  • @DanielRoseman - 谢谢,我包含了导入脚本和 models.py 内容。
  • @DanielRoseman 2.7

标签: python django csv unicode sqlite


【解决方案1】:

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

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

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

(当您只有 ASCII 字节(字节 0-127)时,Django/Python 2 允许您将字节字符串写入 Unicode 属性,因为它们在很多编码中具有相同的映射。ASCII 是“最佳猜测” ' 在 Do What I mean ,但它不可靠,如果你尝试,Python 3 更愿意引发错误。)

所以:

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

或者,一次解码整行:

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

【讨论】:

  • 您的windows-1252 编码不起作用,但您对编码问题的看法当然是正确的。我最终用谷歌文档打开了 xls 文件,然后从那里下载了一个 csv。它在不指定编码的情况下使用该新文件。我的Mac上有中文版的excel,所以它一定是一些奇怪的编码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 2018-11-14
  • 2012-09-15
相关资源
最近更新 更多