[英]How does Django loaddata know which fields make the natural key?
我正在使用Django的dumpdata保存数据,并使用loaddata重新加载它。 我也在使用自然键。 我的模型与此类似:
class LinkManager(models.Manager):
def get_by_natural_key(self, url):
return self.get(url=url)
class Link(models.Model):
objects = LinkManager()
title = models.CharField(max_length=200)
url = models.URLField()
def natural_key(self):
return (self.url, )
如果导出并重新导入数据,则Django会识别出对象已存在,并且不会创建重复项。 如果更改标题,它将正确更新对象。 但是,如果我更改了URL,它将正确地将其视为一个新对象-尽管我忘记标记url
唯一! 它如何猜出我的意图?
django如何知道我的url
字段是自然键? 没有get_natural_fields
函数。 Django可以在类而不是实例上调用natural_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_by_natural_key
,它还首先调用natural_key
。 如果没有该模型的实例,该怎么做?
它只是从构造函数(d'oh!): Model(**data)
创建一个实例,该实例不受数据库支持。 请参阅django.core.serializers.base
build_instance
。 然后, natural_key
对新创建的对象调用natural_key
,并立即get_by_natural_key
检索属于该对象的pk
(如果存在于数据库中)。 这样,Django不需要知道自然键所依赖的字段,它只需要知道如何从数据中获取它即可。 您可以只在检索到的实例上调用save()
,如果它在数据库中,它将有一个pk
并将更新,如果没有,它将创建一个新行。
build_instance
函数的源代码(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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.