Django的loaddata失败的Unicode

时间:2018-06-19 16:55:39

标签: mysql django unicode loaddata

这是模型:

class ListItem(models.Model):
   # id -- PK
   dateCreated = models.DateTimeField(auto_now_add=True)
   dateModified = models.DateTimeField(auto_now_add=True)
   listId = models.IntegerField(null=False)  # required FK => List
   itemId = models.CharField(max_length=8, null=False)
   description = models.CharField(max_length=1024)
   notes = models.CharField(max_length=2048)

   class Meta:
      ordering = ('itemId',)

这是来自灯具文件(json)的有问题的项目:

    {
    "model": "myproject.ListItem",
    "pk": 721,
    "fields": {
        "listId": 26,
        "itemId": "A3",
        "description": "Statystyka Książek Papierowych, Mówionych I Elektronicznych",
        "notes": "Polish Statistical Book and E-book Classification",
        "dateCreated": "2018-05-14 22:05:25",
        "dateModified": "2018-05-14 22:05:25"
    }
}, ...

这是我用来尝试加载数据的命令:

python3 manage.py loaddata listItems.json

这导致了以下错误:

django.db.utils.OperationalError: Problem installing fixture \
'/Users/sloughin/dev/myproject/fixtures/listItems.json': \
Could not load myproject.ListItem(pk=721): \
(1366, "Incorrect string value: '\\xC4\\x85\\xC5\\xBCek...' \
for column 'description' at row 1")

我应该在模型中使用一些标志来表示我希望该字段包含unicode数据吗?

这是在Ubuntu 16.04上针对MySQL数据库运行的,而我正在iMac(OSX 10.13.5)上运行python 3.6.2。我所有其他的loaddata操作都工作正常。

1 个答案:

答案 0 :(得分:0)

好的,我想我明白了。 MySQL数据库的VARCHAR字段默认为utf8,它支持大多数(但不是全部)unicode字符。这就是为什么有些记录还可以,而有些则不行的原因。您必须使用utf8mb4而不是utf8。这增加了数据库字段的宽度,因为它们现在每个字符使用4个字节而不是3个字节(因此对于某些DBMS,您可能还需要将模型中字段的宽度扩大4/3倍),尽管m告诉MySQL字段以字符而不是字节指定。

但是,我们将需要有一个新的迁移文件来使用,因此我将更改其中一个字段的长度为一个字符。

class ListItem(models.Model):
      # id -- PK
      dateCreated = models.DateTimeField(auto_now_add=True)
      dateModified = models.DateTimeField(auto_now_add=True)
      listId = models.IntegerField(null=False)  # required FK => List
      itemId = models.CharField(max_length=8, null=False)
      description = models.CharField(max_length=1025)  # was 1024
      notes = models.CharField(max_length=2048)  

我重跑了python3 manage.py makemigrations

接下来,我转到migrations文件夹并编辑了新的迁移文件(我的文件名为002_auto_20180619_1849.py),该文件包含定义了class Migrations:的{​​{1}}。您会从扩大字段的范围中看到AlterField操作,但是之后您可以追加其他SQL操作,如下所示:

operations

在这里,我将每个SQL语句分成两行,以便您可以阅读。如果您可以直接访问数据库,则也可以在mysql会话中执行此操作,但是我想知道如何在迁移过程中执行此操作。

之前,请运行此迁移,请检查并确保已安装migrations.AlterField(...), migrations.RunSQL( 'alter table myproject_listitem CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'), migrations.RunSQL( 'alter table myproject_listitem CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'), migrations.RunSQL( 'alter table myproject_listitem change description description VARCHAR(1366) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'), migrations.RunSQL( 'alter table myproject_listitem change notes notes VARCHAR(2731) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'), 。如果不是,则sqlparse或将其包含在您的虚拟环境或Docker容器中作为要求。然后:

pip3 install sqlparse

在那之后,我能够运行python3 manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, myproject, sessions Running migrations: Applying myproject.0002_auto_20180619_1849... OK ,并且一切正常!