2010-09-10 5 views
4

C'est amusant :-)Un indice sur cette erreur avec une relation générique en utilisant Django Orm?

En travaillant sur un EAV, nous injectons un gestionnaire de relation générique à l'exécution dans un modèle.

model_cls est une classe et une classe EavValue a une relation générique pointant vers elle. Il fonctionne très bien de EavValues à un model_cls, mais dans l'autre sens nous avons besoin d'injecter un accesseur pour faciliter les choses:

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') 

Encore une fois, nous le faisons à l'exécution parce que nous voulons le faire fonctionner avec intouchable 3ème libs parti.

Alors que UnitTesting avec une classe Patient comme model_cls, nous obtenons l'erreur suivante:

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'. 

Maintenant, nous avons trouvé que la solution facile est de changer soit le deuxième paramètre de contribute_to_class ou related_name dans GenericRelation, mais il doesn 't! Nous obtenons exactement la même erreur, seulement avec un nom différent.

Deuxième chose étrange, exécutant les mêmes tests unitaires avec Sqlite au lieu de MySql: tout passe.

De plus, peu importe l'ordre ou les tests, on obtient toujours cette erreur lors des deuxièmes tests. Puisque ce processus se passe dans une méthode register et que nous appelons register et unregister lors de l'installation et de la démontage, je suppose que notre méthode unregister est imparfaite.

Dernier fait étrange: nous obtenons l'erreur lors de l'exécution unittest, mais nous sommes incapables de le reproduire manuellement. Pire, sur l'ordinateur de mon collègue, il n'y a pas d'erreur quand on utilise la même version de Python, Django, Ubuntu et MySQL.

Nous avons résolu beaucoup de dures mais nous sommes un peu coincés sur celui-ci donc toute idée appréciée.

MISE À JOUR:

Nouveaux indices pour ce grand jeu:

Les erreurs sont soulevées à partir de cet extrait dans django.core.management.validation, sur la ligne 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)) 

Pour nous r.get_accessor_name() == rel_name est vrai, car les deux sont "Patient".

MISE À JOUR 2:

Lorsque l'on ajoute une application qui register un modèle. Tout modèle, le problème n'apparaît plus. Tellement pour la théorie unregister ...

Nous avons deux erreurs symétriques (les deux côtés de la relation).Suppression de related_name réprimer une des erreurs 0_o

Répondre

1

trouvé la solution

Ajout d'une relation générique sur mettre une référence dans la classe modèle _meta.local_many_to_many attribut qui est une liste. Django vérifie cela mais ne fournit aucun moyen de s'en débarrasser. La correction est:

# 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 
Questions connexes