4

这是一个有趣的:-)

在 EAV 上工作时,我们在模型中在运行时注入一个通用关系处理程序。

model_cls是任何类,并且EavValue类具有指向它的通用关系。从EavValuesto a可以正常工作model_cls,但另一方面,我们需要注入一个访问器来简化事情:

generic_relation = generic.GenericRelation(EavValue,
                                               object_id_field='entity_id',
                                               content_type_field='entity_ct',
                                               related_name=model_cls.__name__)
generic_relation.contribute_to_class(model_cls, 'eav_values')

同样,我们在运行时这样做是因为我们想让它与不可触及的 3rd 方库一起工作。

在使用Patientas 类进行单元测试时model_cls,我们收到以下错误:

eav_ng.patient: Accessor for m2m field 'eav_values' clashes with related m2m field 'EavValue.Patient'. Add a related_name argument to the definition for 'eav_values'.

现在,我们认为最简单的解决方法是更改contribute_to_class​​ 或related_namein的第二个参数GenericRelation,但事实并非如此!我们得到完全相同的错误,只是名称不同。

第二个奇怪的事情,使用 Sqlite 而不是 MySql 运行相同的单元测试:全部通过。

更重要的是,无论顺序或测试,我们总是在第二次测试时得到这个错误。由于这个过程发生在一个register方法中,并且我们在设置和拆除时调用registerunregister我猜我们的unregister方法是不完美的。

最后一个奇怪的事实:我们在运行 unittest 时遇到错误,但我们无法手动重现它。最糟糕的是,在我同事的计算机上,当我们使用相同版本的 Python、Django、Ubuntu 和 MySQL 时,它不会出现错误。

我们解决了很多困难的问题,但我们有点卡在这个问题上,所以任何线索都值得赞赏。

更新:

这个伟大游戏的新线索:

在 django.core.management.validation 中的这个片段中引发了错误,第 245 行(django 1.2.1):

for r in rel_opts.get_all_related_many_to_many_objects():
    if r.field is not f:
        if r.get_accessor_name() == rel_name:
            e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
        if r.get_accessor_name() == rel_query_name:
            e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))

对我们来说r.get_accessor_name() == rel_name是真实的,因为两者都是“耐心”。

更新 2:

当我们添加register一个模型的应用程序时。任何型号,问题不再出现。理论就这么多了unregister……

我们有两个对称的错误(关系的两边)。删除related_name抑制错误之一 0_o

4

1 回答 1

1

找到了解决方案

在模型类_meta.local_many_to_many属性中添加一个通用关系,该属性是一个列表。Django 对此进行检查,但没有提供摆脱它的方法。修复是:

    # remove remaining reference to the generic relation
    for field in model_cls._meta.local_many_to_many:
        if field.name == 'eav_value': # your related name
            model_cls._meta.local_many_to_many.remove(field)
            break
于 2010-09-10T12:48:17.220 回答