Search code examples
pythondjangoabstract-classforeign-key-relationshipdjango-south

Django ForeignKey in abstract model class and multiple drived classes causes name clash


I defined an abstract class and it has a ForeignKey. I have multiple derived model classes, but when I try to generate the schema migration script, south presents me an error.

class BlogEntryBase(models.Model):
    author = models.CharField(null=True, blank=True, max_length=100)
    title = models.CharField(null=True, blank=True, max_length=255)
    created_by = models.ForeignKey("main.UserProfile", verbose_name="Created By", related_name="%(class)s_set", blank=False, null=False)

class CatBlogEntry(BlogEntryBase):
    pass

class DogBlogEntry(BlogEntryBase):
    pass

Error messages:

animal.catblogentry: Accessor for field 'created_by' clashes with related field 'UserProfile.catblogentry_set'. Add a related_name argument to the definition for 'created_by'.
animal.catblogentry: Reverse query name for field 'created_by' clashes with related field 'UserProfile.catblogentry_set'. Add a related_name argument to the definition for 'created_by'.
animal.dogblogentry: Accessor for field 'created_by' clashes with related field 'UserProfile.dogblogentry_set'. Add a related_name argument to the definition for 'created_by'.
animal.dogblogentry: Reverse query name for field 'created_by' clashes with related field 'UserProfile.dogblogentry_set'. Add a related_name argument to the definition for 'created_by'.

As you see, I already specify related_name argument. I guess the problem is that on the UserProfile side there will be two set objects, and they somehow clash? As you see I tried to permutate the related name like "%(class)s", but that's not enough. I don't want to move up the foreign key class to the derived classes, because probably I'll have to repeat view and form code because of that. Anyone has some advice? My goal is DRY. Keep the two blog tables separate, but handle them with common templates, view and form codes.

Note: the "main.UserProfile" is a string to avoid circular module dependency.


Solution

  • I simplified my example so much that I actually left out the cause of the error. I had actually two Foreign keys, and 8 error messages total. The ForeignKeys referred to the same entity, UserProfile: created_by, modified_by. The problem was that I used simply

    related_name="%(class)s_set"
    

    while I needed to distinguish these two

    related_name="%(class)s_something_unique_set"
    

    Like so:

    class BlogEntryBase(models.Model):
        author = models.CharField(null=True, blank=True, max_length=100)
        title = models.CharField(null=True, blank=True, max_length=255)
        created_by = models.ForeignKey("main.UserProfile", verbose_name="Created By", related_name="%(class)s_created_by_set", blank=False, null=False)
        modified_by = models.ForeignKey("main.UserProfile", verbose_name="Modified By", related_name="%(class)s_modified_by_set", blank=False, null=False)
    
    class CatBlogEntry(BlogEntryBase):
        pass
    
    class DogBlogEntry(BlogEntryBase):
        pass