Python Django loaddata如何知道哪些字段构成自然键?
我使用Django的dumpdata来保存数据,并使用loaddata来重新加载数据。我也使用自然键。我的模型与此类似:Python Django loaddata如何知道哪些字段构成自然键?,python,django,django-orm,Python,Django,Django Orm,我使用Django的dumpdata来保存数据,并使用loaddata来重新加载数据。我也使用自然键。我的模型与此类似: 类链接管理器(models.Manager): def get_by_natural_键(self,url): 返回self.get(url=url) 类链接(models.Model): 对象=链接管理器() title=models.CharField(最大长度=200) url=models.URLField() def自然_键(自): 返回(self.url,) 如
类链接管理器(models.Manager):
def get_by_natural_键(self,url):
返回self.get(url=url)
类链接(models.Model):
对象=链接管理器()
title=models.CharField(最大长度=200)
url=models.URLField()
def自然_键(自):
返回(self.url,)
如果我导出并重新导入数据,Django会识别出对象已经存在,并且不会创建重复项。如果我更改标题,它将正确更新对象。但是,如果我更改URL,它会正确地将其视为新对象-尽管我忘记标记URL
unique!它怎么猜出我的意图
django如何知道我的url
字段是自然键?没有get\u natural\u字段
函数。Django可以调用类上的natural\u key
,而不是一个实例来获取字段,但这似乎非常脆弱:
>>> [f.field_name for f in Link.natural_key(Link)]
['url']
我想知道这一点的原因是,我正在编写自己的特殊导入器(以取代我对loaddata的使用),并且我希望利用自然关键点,而不必硬编码每个模型的自然关键点(或“标识”字段)。目前,我通过对象的唯一字段“识别”对象-我做:
obj, created = Model.objects.update_or_create(**identifying, defaults=other)
但Django似乎选择了不同的“识别”字段。我想我已经找到了答案。Django不只是调用
get\u by\u natural\u key
,它首先调用natural\u key
。如果没有模型的实例,它是如何做到的
它只是从构造函数(d'oh!):Model(**data)
创建一个实例,而不是由数据库支持。请参见django.core.serializers.base
中的build\u实例
。然后它对新创建的对象调用natural\u key
,并立即get\u by\u natural\u key
,以检索属于该对象的pk
,如果该对象存在于数据库中。这样,Django就不需要知道自然键依赖于哪些字段,只需要知道如何从数据中获取它。您只需对检索到的实例调用save()
,如果它在数据库中,它将有一个pk
,并将更新,如果没有,它将创建一个新行
build\u实例
函数的来源(Django 1.11.2):
我想我已经发现了。Django不只是调用
get\u by\u natural\u key
,它首先调用natural\u key
。如果没有模型的实例,它是如何做到的
它只是从构造函数(d'oh!):Model(**data)
创建一个实例,而不是由数据库支持。请参见django.core.serializers.base
中的build\u实例
。然后它对新创建的对象调用natural\u key
,并立即get\u by\u natural\u key
,以检索属于该对象的pk
,如果该对象存在于数据库中。这样,Django就不需要知道自然键依赖于哪些字段,只需要知道如何从数据中获取它。您只需对检索到的实例调用save()
,如果它在数据库中,它将有一个pk
,并将更新,如果没有,它将创建一个新行
build\u实例
函数的来源(Django 1.11.2):
def build_instance(Model, data, db):
"""
Build a model instance.
If the model instance doesn't have a primary key and the model supports
natural keys, try to retrieve it from the database.
"""
obj = Model(**data)
if (obj.pk is None and hasattr(Model, 'natural_key') and
hasattr(Model._default_manager, 'get_by_natural_key')):
natural_key = obj.natural_key()
try:
obj.pk = Model._default_manager.db_manager(db).get_by_natural_key(*natural_key).pk
except Model.DoesNotExist:
pass
return obj