django loaddata对unicode失败

dwbf0jvd  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(330)

模型如下:

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

下面是fixture文件(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数据吗?
这是针对ubuntu16.04上的mysql数据库运行的,我在imac(osx10.13.5)上运行python3.6.2。我所有其他的loaddata操作都很好。

dwthyt8l

dwthyt8l1#

好吧,我想我知道了。mysql数据库varchar字段默认为utf8,它支持大多数(但不是全部)unicode字符。这就是为什么有些记录是好的,而有些记录不是。必须使用utf8mb4而不是utf8。这增加了数据库字段的宽度,因为它们现在每个字符使用4字节而不是3字节(因此对于某些dbms,您可能还需要将模型中字段的宽度扩大4/3倍),尽管我被告知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\u auto\u 20180619\u 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 或者将其作为一项要求包含在虚拟环境或docker容器中。然后:

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 一切都很顺利!

相关问题