Any clue about this error with a generic relation using Django Orm?

It's fun: -)

When working on EAV, we introduce a common relationship handler at run time in the model.

model_cls is any class, and the EavValue class has a common relationship that points to it. It works great from EavValues to model_cls , but on the other hand, we need to introduce an accessory to make things easier:

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

Again, we do this at runtime because we want it to work with untouchable third-party libraries.

During unittesting with the class Patient as model_cls we get the following error:

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

Now we thought that it was easy to fix if we changed either the second contribute_to_class parameter or the related_name in GenericRelation , but that is not so! We get exactly the same error, only with a different name.

The second strange thing, running the same unittests with Sqlite instead of MySql: everything goes through.

What else does not matter for the order or tests, we always get this error during the second tests. Since this process happens by the register method and we call register and unregister when setting up and unregister , I assume that our unregister method unregister imperfect.

Last strange fact: we get an error when starting unittest, but we cannot reproduce it manually. Worst of all, on my colleague's computer, it does not get an error while we use the same version of Python, Django, Ubuntu and MySQL.

We decided a lot of tough ones, but we seemed to be stuck on this, so any sign was appreciated.

UPDATE:

New tips for this wonderful game:

Errors arise from this snippet in django.core.management.validation, on line 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)) 

For us, r.get_accessor_name() == rel_name is true, since both are "patients."

UPDATE 2:

When we add the application, register model. Any model, the problem no longer appears. So much for unregister theory ...

We have two symmetrical errors (both sides of the relationship). Removing related_name suppresses one of the errors 0_o

+4
source share
1 answer

Solution found

Adding a common relation to place the link in the class class attribute _meta.local_many_to_many , which is a list. Django checks this, but does not give the opportunity to get rid of it. Correction:

  # 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 
+1
source

All Articles