Issue: Problem related_name collision ?
Author: ghost
State: closed
Created: 2013-12-28 22:48:54

If i try to import the following module i got the error:

```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "db.py", line 102, in <module>
    class Schuelerkontakt(Kontakt):
File "/usr/lib/python2.7/site-packages/peewee.py", line 2570, in __new__
    attr.add_to_class(cls, name)
File "/usr/lib/python2.7/site-packages/peewee.py", line 800, in add_to_class
    raise AttributeError(error % params)
AttributeError: Foreign key: schuelerkontakt.typ related name "typ_des_kontakts" 
collision with foreign key using same related_name.
```

I'm not able to fix it. _same related_name_ - i don't see this related_name twice?

The Module:

```
from peewee import *


database = SqliteDatabase(None)   


class SqliteModel(Model):
    """abstract class
    """
    class Meta:
        database = database

    def __str__(self):
        return self.__unicode__().encode(ENC)
    def __repr__(self):
        return "<%s>" % (self.__str__(),)

class SimpleModel(SqliteModel):
    """abstract class
    """
    name = CharField(max_length=50)

### real

class Kontakttyp(SimpleModel):
    beschreibung = CharField(max_length=20, null=True)


class Kontaktkategorie(SimpleModel):
    beschreibung = CharField(max_length=30, null=True)


class Person(SqliteModel):
    nachname = CharField(max_length=40)
    vorname = CharField(max_length=25)
    gebdat = DateField(null=True)

    def __unicode__(self):
        out = u"%s %s" % (self.nachname, self.vorname)
        if self.gebdat:
            out += " (%s)" % (self.gebdat,)
        return out

    def __cmp__(self, o):
        if not isinstance(o, Person):
            err = "only Schueler objects comparable"
            raise ValueError(err)

        if o.nachname > self.nachname:
            return -1
        elif o.nachname == self.nachname:
            if o.vorname > self.vorname:
                return -1
            elif o.vorname == self.vorname:
                return 0
            else:
                return 1
        else:
            return 1


class Lehrkraft(Person):
    kuerzel = CharField(max_length=3)
    klasse = CharField(max_length=3, null=True)

    class Meta:
        order_by = ('nachname', 'vorname')


class Schueler(Person):
    klasse = CharField(max_length=3)
    zweig = CharField(null=True, max_length=4)
    spitzname = CharField(max_length=20, null=True)

    class Meta:
        order_by = ('nachname', 'vorname')

    def __unicode__(self):
        out = Person.__unicode__(self)
        if self.zweig:
            out += " [Klasse: %s (%s)]" % (self.klasse, self.zweig)
        else:
            out += " [Klasse: %s]" % (self.klasse,)
        return out


class Kontakt(SqliteModel):
    typ = ForeignKeyField(Kontakttyp,
                          related_name='typ_des_kontakts')
    bezeichner = CharField(max_length=40)
    kategorie = ForeignKeyField(Kontaktkategorie,
                                null=True,
                                related_name='kategorie_des_kontakts')

    def __unicode__(self):
        return u"%s: %s " % (self.typ, self.bezeichner)
        if self.kontaktkategorie:
            return out + "[%s]" % (self.kategorie,)


class Schuelerkontakt(Kontakt):
    schueler = ForeignKeyField(Schueler,
                               related_name='kontakt_des_schuelers')


class Lehrerkontakt(Kontakt):
    lehrer = ForeignKeyField(Lehrkraft,
                             related_name='kontakt_der_lehrkraft')
```


Since `Schuelerkontakt` extends `Kontakt`, it also includes copies of the various foreign keys.  For instance `typ = ForeignKeyField(Kontakttyp, related_name='typ_des_kontakts')`.

That sets up an attribute on `Kontakttyp` named `typ_des_kontakts` that initially points to `Kontakt`.  When we get to `Schuelerkontakt` (which has the same `typ = ForeignKeyField(...)` because of inheritance) the related name collides with the existing one.

My suggestion would be to rewrite your models like so:

``` python
class Kontakt(SqliteModel):
    typ = ForeignKeyField(Kontakttyp,
                          related_name='typ_des_kontakts')
    bezeichner = CharField(max_length=40)
    kategorie = ForeignKeyField(Kontaktkategorie,
                                null=True,
                                related_name='kategorie_des_kontakts')

    def __unicode__(self):
        return u"%s: %s " % (self.typ, self.bezeichner)
        if self.kontaktkategorie:
            return out + "[%s]" % (self.kategorie,)


class Schuelerkontakt(Kontakt):
    typ = ForeignKeyField(Kontakttyp,
                          related_name='typ_des_schueler_kontakts')
    schueler = ForeignKeyField(Schueler,
                               related_name='kontakt_des_schuelers')
    kategorie = ForeignKeyField(Kontaktkategorie,
                                null=True,
                                related_name='kategorie_des_shuelerkontakts')


class Lehrerkontakt(Kontakt):
    typ = ForeignKeyField(Kontakttyp,
                          related_name='typ_des_lehrer_kontakts')
    lehrer = ForeignKeyField(Lehrkraft,
                             related_name='kontakt_der_lehrkraft')
    kategorie = ForeignKeyField(Kontaktkategorie,
                                null=True,
                                related_name='kategorie_des_lehrerkontakts')
```

Pardon me if I butchered the names.

---

As an aside, just wanted to make sure you understood how model inheritance works.  It does not do anything clever as far as multi-table joins or polymorphism at the row-level.


Thanks,

i should have red your docs in detail - sorry. The document part [Inheriting model metadata](http://peewee.readthedocs.org/en/latest/peewee/models.html#inheriting-model-metadata) has gone unnoticed to my _/head/null_  :(


No prob, the inheritance stuff can be very confusing.