Bare with me it's a long story...

When deleting an object I was getting this error from Django:

'RelatedManager' object has no attribute '_collect_sub_objects'

The reason was an attribute name clash on a base class. Finding the
reason took some time so here's the low down in case any one else runs
in to this.

In one app I had a model Company:

    class Company(models.Model):
        name = models.CharField(max_length=1024)

and in another app I had a model AdClient:

    class AdClient(models.Model):
        company = models.ForeignKey(Company, related_name='client')

Then some time later I wrote a new app inheriting from Company as:

    class Client(Company):
        name = models.CharField(max_length=1024)

... and I forgot about the AdClient model.

The new sub-class, Client, causes a new attribute to appear in its
parent class as 'client' linking to possible Client sub-classes of
Company, since if the parent is deleted the child has to go too. But
the AdClient model has linked into Company as a related field with the
same name - 'client'. Django is clever and will detect this name clash
*if it knows about*.

So how did this happen?

It turns out the AdClient application was not installed - i.e. not
listed in settings.INSTALLED_APPS. So the Django validator never
picked up the clash.

But if the app is not installed how can the clash happen? Well, I'd
written some admin views (not Django admin views my own simpler
versions) and though the app was not installed, the URLs for the (not
installed app's) admin views  were still included in my parent admin
URLconf. This caused the associated apps to get pulled in to the list
of loaded apps at run time which in turn registers the related models.
It turns out the dynamic registering of related models does not check
for clashes of attribute name. (At least as far as I can tell - there
was no exception).  So a non-existent app gets listed as related to a
base class and when the base class is deleted Django tries to follow a
relationship which is a dead end and throws an exception.

So the lesson is: don't include URLs for apps which are not installed.
Even if they are never visited they will cause their apps to get
pulled in at runtime.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to