首页 文章

Django loaddata因unicode而失败

提问于
浏览
0

这是模型:

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

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

    但是,我们需要有一个新的迁移文件才能使用,所以我要将其中一个字段更改为一个char更长 .

    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

    接下来,我转到迁移文件夹并编辑了新的迁移文件(我的名称为002_auto_20180619_1849.py),其中包含 class Migrations: ,其中定义了 operations . 您将看到AlterField操作使该字段更宽,但在此之后您可以附加其他SQL操作,如下所示:

    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;'),
    

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

    在运行此迁移之前,请检查以确保安装了 sqlparse . 如果没有,那么 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
    

    在那之后,我能够运行 python3 manage.py loaddata listItems.json ,一切正常!

相关问题