4

我正在尝试使用 2 组夹具提供初始数据。第一个夹具格式如下所示。

  {
    "pk": 1,
    "model": "data.Person",
    "fields": {
      "full": "Anna-Varney",
      "num": "I",
      "short": "Anna-Varney"
    }
  },

我先加载它,它在大约 1-2 小时内加载良好。我的 movie.json 格式如下所示:

  {
    "pk": 1,
    "model": "data.Film",
    "fields": {
      "date": "2005-08-01",
      "rating": 8.3,
      "actors": [
        [
          "Anna-Varney"
        ]
      ],
      "name": "Like a Corpse Standing in Desperation (2005) (V)"
    }
  },

并且加载电影固定装置花费了很长时间,目前是 20 小时,而且我的电脑在运行时速度很慢。我在 2 个月前加载了类似的装置,除了我使用 MySQL(我现在正在使用 Postgres)并且我在我的模型中添加了日期字段。过去将电影设备加载到我的旧 MySQL 数据库时,只需要 2-3 个小时。有没有办法确定夹具加载部分在哪一步或是否已冻结?

作为参考,我的模型是:

class PersonManager(models.Manager):
    def get_by_natural_key(self, full):
        return self.get(full=full)

class Person(models.Model):
    objects = PersonManager()
    full = models.CharField(max_length=100,unique = True)
    short = models.CharField(max_length=100)
    num = models.CharField(max_length=5)
    def natural_key(self):
        return (self.full,)

    def __unicode__(self):
        return self.full


class Film(models.Model):
    name = models.TextField()
    date = models.DateField()
    rating = models.DecimalField(max_digits=3 , decimal_places=1)
    actors = models.ManyToManyField('Person')

    def __unicode__(self):
        return self.name
4

3 回答 3

2

在大多数情况下,您可以通过以编程方式加载转储数据并使用bulk_create

例子:

from collections import defaultdict
from django.core import serializers                                                                     

obj_dict = defaultdict(list)
deserialized = serializers.deserialize('json', open('my_fixtures.json'))
# organize by model class
for item in deserialized:
  obj = item.object
  obj_dict[obj.__class__].append(obj) 

for cls, objs in obj_dict.items():
  cls.objects.bulk_create(objs)
于 2018-11-25T00:45:58.273 回答
2

如果您通过命令行加载您的灯具:

python manage.py loaddata --database=MY_DB_LABEL fixtures/my_fixture.json;

或者也许通过 shell 以编程方式:

os.system('python manage.py loaddata --database=%s fixtures/my_fixture.json;' % MY_DB_LABEL)

夹具加载会很。(我没有调查原因。大概是进行了许多不必要的中间数据库保存。)


解决方案:切换到使用单个事务通过 python 以编程方式加载您的固定装置:

from django.db import transaction
from django.core.management import call_command

with transaction.atomic(using=MY_DB_LABEL):
    call_command('loaddata', 'fixtures/my_fixture.json', database=MY_DB_LABEL)
    call_command('loaddata', 'fixtures/my_other_fixture.json', database=MY_DB_LABEL)

夹具加载将大大加快速度。


注意这里的databaseusing参数是可选的。如果您使用的是单个数据库,则它们是不必要的。但是,如果您像我一样使用多个数据库,您可能希望使用它来确保将夹具数据加载到哪个数据库中。

于 2021-02-11T17:16:01.850 回答
1

因为 Django 在自动提交模式下运行,它要求数据库真正确定在创建每个对象后,它会立即保存并同步到驱动器盘片上的物理位置。这将保存的对象数量限制为磁盘盘片的速度。

您需要使用@transaction.atomic装饰器或with transaction.atomic():上下文管理器来允许数据库确保所有内容仅安全保存一次 - 最后。

您可以在 Django 文档中阅读有关事务的更多信息

在将 PostgreSQL 与 Django 一起使用时,我什至建议在数据库配置中设置ATOMIC_REQUESTS为。True这样,每个浏览器请求都将自动在一个事务中提供服务,并且只有在结果视图成功运行时才会提交。

于 2013-10-10T22:58:39.997 回答