在 Django 中使用 natural_keys 时,如何区分创建和更新?

Posted

技术标签:

【中文标题】在 Django 中使用 natural_keys 时,如何区分创建和更新?【英文标题】:When using natural_keys in Django, how can I distinguish between creates & updates? 【发布时间】:2021-02-22 15:01:00 【问题描述】:

在 Django 中,我经常将模型装置从一个数据库复制到另一个数据库。我的模型在序列化过程中使用natural_keys(尽管我不确定这是否相关)。如何确保一个数据库中已更新的实例不会插入到另一个数据库中?

考虑以下代码:

models.py:

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

class Author(models.Model):
  objects = AuthorManager()
  name = models.CharField(max_length=100)
  def natural_key(self):
    return (self.name,)

现在,如果我创建一个名为“William Shakespeare”的作者并通过python manage.py dumpdata --natural_keys 将其转储到固定装置,我将使用以下类型的文件结束:

[
  
    "model": "myapp.author",
    "fields": 
      "name": "Wiliam Shakespeare"
    
  
]

我可以将它加载到另一个数据库中,它将创建一个名为“William Shakespeare”的作者。

但是,如果我在原始数据库中将该作者重命名为“Bill Shakespeare”并重新创建夹具并将其加载到另一个数据库中,那么它将创建另一个 new 作者命名为“Bill Shakespeare”,而不是更新现有Author 的名字。

关于如何解决这个问题的任何想法?

【问题讨论】:

想到的一个想法是使用 uuids 作为 natural_key(或者实际上只是作为 id 字段本身)。 呃,自然键的重点是不要使用无意义的键。 【参考方案1】:

您正在使用固定装置来完成它的用途:同步数据库。它用于填充空数据库。特别是,“删除”不能在夹具中表达。基于自然键的更新可以表示为插入+删除。

现在您可以通过不使用自然键来解决此问题,但是数据库之间的主键必须相同。如果目标数据库从另一个源接收插入,那么这是一个问题,因为更新将发生在错误的对象上。

简而言之:使用同步/复制工具来同步数据库,使用夹具进行迁移和测试。尝试使用固定装置进行同步很容易出错。

【讨论】:

以上是关于在 Django 中使用 natural_keys 时,如何区分创建和更新?的主要内容,如果未能解决你的问题,请参考以下文章

在django中使用django_debug_toolbar

Django:在管理界面中使用 TinyMCE 4

在 django-crispy 按钮名称中使用 django 模板变量

使用 django-import-export 在 django 迁移中的外键

如何使用 Django Rest Framework 在 Django 中进行操作日志记录

如何在 Django 中使用模式?