3

如何加载 Django 固定装置,以使通过自然键引用的模型不会与预先存在的记录冲突?

我正在尝试加载这样的夹具,但我从我的 MySQL 后端收到 IntegrityErrors,抱怨 Django 试图插入重复记录,这没有任何意义。

据我了解Django的自然关键特性,为了完全支持dumpdata和loaddata的使用,你需要在模型中定义一个natural_key方法,get_by_natural_key在模型的管理器中定义一个方法。

因此,例如,我有两个模型:

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

class Person(models.Model):

    objects = PersonManager()

    name = models.CharField(max_length=255, unique=True)

    def natural_key(self):
        return (self.name,)

class BookManager(models.Manager):
    def get_by_natural_key(self, title, *person_key):
        person = Person.objects.get_by_natural_key(*person_key)
        return self.get(title=title, person=person)

class Book(models.Model):

    objects = BookManager()

    author = models.ForeignKey(Person)

    title = models.CharField(max_length=255)

    def natural_key(self):
        return (self.title,) + self.author.natural_key()
    natural_key.dependencies = ['myapp.Person']

我的测试数据库已经包含一个示例 Person 和 Book 记录,我用它来生成夹具:

[
    {
        "pk": null, 
        "model": "myapp.person", 
        "fields": {
            "name": "bob"
        }
    }, 
    {
        "pk": null, 
        "model": "myapp.book", 
        "fields": {
            "author": [
                "bob"
            ], 
            "title": "bob's book", 
        }
    }
]

我希望能够使用这个夹具并将其加载到我的数据库的任何实例中以重新创建记录,无论它们是否已经存在于数据库中。

但是,当我运行时,python manage.py loaddata myfixture.json我得到了错误:

IntegrityError: (1062, "Duplicate entry '1-1' for key 'myapp_person_name_uniq'")

为什么 Django 试图重新创建 Person 记录而不是重用已经存在的记录?

4

2 回答 2

1

事实证明,该解决方案需要对 Django 的loaddata命令进行非常小的补丁。由于 Django 开发人员不太可能接受这样的补丁,因此我将它分叉到我的各种 Django 管理相关增强包中。

The key code change (lines 189-201 of loaddatanaturally.py) simply involves calling get_natural_key() to find any existing pk inside the loop that iterates over the deserialized objects.

于 2015-03-30T16:22:38.283 回答
0

实际上 loaddata 不应该与数据库中的现有数据一起使用,它通常用于模型的初始加载。看看这个问题的另一种方法:Import data into Django model with existing data?

于 2012-06-10T09:11:31.900 回答