2010-09-10 68 views
4

這是一個有趣的:-)任何關於使用Django Orm的泛型關係的錯誤線索?

工作在一個EAV上,我們在模型的運行時注入一個通用關係處理程序。

model_cls是任何類,而EavValue類具有指向它的通用關係。它工作正常,從EavValuesmodel_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') 

再次,我們這樣做,在運行時,因爲我們希望把它與賤民第三工作黨的庫。

雖然有Patient類爲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_classGenericRelationrelated_name第二個參數,但它不「T!我們得到完全相同的錯誤,只能使用不同的名稱。

第二件奇怪的事情,用Sqlite代替MySql運行相同的單元測試:全部通過。

更重要的是,無論順序或測試,我們總是在第二次測試中得到這個錯誤。由於這個過程發生在register方法中,我們在設置和拆除時調用registerunregister,我猜我們的unregister方法是不完美的。

最後一個奇怪的事實:運行unittest時出現錯誤,但我們無法手動重現它。最糟糕的是,在我的同事電腦上,當我們使用相同版本的Python,Django,Ubuntu和MySQL時,它沒有得到錯誤。

我們解決了很多困難的問題,但是我們對這個問題仍然有所瞭解,所以我們都非常欣賞。

UPDATE:

爲這個偉大的遊戲的新線索:

錯誤從這個片段在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

回答

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