Riz*_*Riz 8 django natural-key generic-foreign-key
我有以下内容:
target_content_type = models.ForeignKey(ContentType, related_name='target_content_type')
target_object_id = models.PositiveIntegerField()
target = generic.GenericForeignKey('target_content_type', 'target_object_id')
Run Code Online (Sandbox Code Playgroud)
我想dumpdata --natural为这种关系发出一个自然的关键.这可能吗?如果没有,是否有一种替代策略不会将我绑定到目标的主键?
TL; DR - 目前没有明智的做法,没有创建自定义Serializer/ Deserializer对.
与具有通用关系模型的问题是,Django不看target可言,只能作为一个字段target_content_type和target_object_id,并尝试序列化和反序列化单独他们.
负责序列化和反序列化Django模型中的类的模块django.core.serializers.base和django.core.serializers.python.所有其他(xml,json和yaml)扩展其中任何一个(和python扩展base).字段序列化是这样完成的(无关的行无效):
for obj in queryset:
for field in concrete_model._meta.local_fields:
if field.rel is None:
self.handle_field(obj, field)
else:
self.handle_fk_field(obj, field)
Run Code Online (Sandbox Code Playgroud)
这是第一个复杂问题:ContentType处理好的外键,使用我们预期的自然键.但是由PositiveIntegerField处理handle_field,这是这样实现的:
def handle_field(self, obj, field):
value = field._get_val_from_obj(obj)
# Protected types (i.e., primitives like None, numbers, dates,
# and Decimals) are passed through as is. All other values are
# converted to string first.
if is_protected_type(value):
self._current[field.name] = value
else:
self._current[field.name] = field.value_to_string(obj)
Run Code Online (Sandbox Code Playgroud)
即,这里定制的唯一可能性(子类化PositiveIntegerField和定义自定义value_to_string)将没有任何效果,因为序列化程序不会调用它.将数据类型更改为target_object_id除整数之外的其他内容可能会破坏许多其他内容,因此它不是一个选项.
在这种情况下,我们可以定义我们的自定义handle_field来发出自然键,然后是第二个并发症:反序列化就像这样完成:
for (field_name, field_value) in six.iteritems(d["fields"]):
field = Model._meta.get_field(field_name)
...
data[field.name] = field.to_python(field_value)
Run Code Online (Sandbox Code Playgroud)
即使我们自定义了该to_python方法,它也会field_value在对象的上下文中单独作用.使用整数时不是问题,因为它将被解释为模型的主键,无论它是什么模型.但是为了反序列化一个自然键,首先我们需要知道该键属于哪个模型,并且除非我们获得对该对象的引用(并且该target_content_type字段已被反序列化),否则该信息不可用.
正如您所看到的,这不是一项不可能完成的任务 - 支持泛型关系中的自然键 - 但要实现这一点,需要在序列化和反序列化代码中更改许多内容.必要的步骤(如果有人感觉到任务)是:
Field扩展PositiveIntegerField- 调用引用的模型' natural_key和get_by_natural_key;handle_field器以调用编码器(如果存在);field_value而且还传递解码的参考ContentType.| 归档时间: |
|
| 查看次数: |
1058 次 |
| 最近记录: |