Issue: Inheritance with ForeignKeyFields
Author: judemille
State: closed
Created: 2017-11-21 02:55:46

When I try to inherit a class with a ForeignKeyField, I get an AttributeError about my related_name already being in use. I want all of the inheriting classes to share the same field in the foreign model so that they can be counted together. Is this possible?

Can you provide an example? I'm not sure I follow about inheriting classes.

You can disable backref validation by specifying:

```python
class MyModel(Model):
    class Meta:
        validate_backrefs = False
```

Also, so long as you aren't explicitly setting the `related_name`, inherited classes would dynamically set it  based on the class name:

```python
class Foo(Model): pass

class Bar(Model):
    foo = ForeignKeyField(Foo)

class Baz(Bar): pass

# Foo.bar_set -> related Bar objects
# Foo.baz_set -> related Baz objects
```

Is this your point?

```python
# common.py
class Foo(Model):
    pass

class Bar(Model):
    foo = ForeignKeyField(foo_proxy, related_name='bars')
```

```python
# sub1.py
class Foo(common.Foo):
    pass

class Bar(common.Foo):
    pass
```

```python
# sub2.py
class Foo(common.Foo):
    pass

class Bar(common.Bar):
    pass
```


@coleifer I want the inheriting classes and the base classes to share the same field in the foreign class so that they can all be grouped together. Is that possible? I'm not sure what the backref validation means

I don't understand what "foreign class" means, or "grouped together" means?

```python
class Foo(Model):
    pass

class Bar(Model):
    foothing = ForeignKeyField(Foo, related_name='bars')

class Baz(Bar):
    pass
```

I want both Bar and Baz to be in the bars field of Foo

```python
class Foo(Model):
    @property
    def bars(self):
        return [] + self.bar_set + self.baz_set

class Bar(Model):
    foothing = ForeignKeyField(Foo)

class Baz(Bar):
    pass
```

@FireFaced -- that doesn't work how you think it might. `Bar` and `Baz` are two separate tables. The backref (`bars`) is a select query that is pre-filtered.

So, for example:

```python
f = Foo(id=1337)
f.bars  # SELECT * FROM bar WHERE foothing_id=1337
```

Thus, a back-ref is limited to a single table. The example from @yanghg-basefx may work but is also inefficient in that it executes 2 queries and coerces to a list, potentially using a lot of memory if the result sets are large.

So how could I implement it so that I can see all types of Bar? Would I end
up using a different type of field or something?

On Mon, Nov 27, 2017, 10:34 Charles Leifer <notifications@github.com> wrote:

> @FireFaced <https://github.com/firefaced> -- that doesn't work how you
> think it might. Bar and Baz are two separate tables. The backref (bars)
> is a select query that is pre-filtered.
>
> So, for example:
>
> f = Foo(id=1337)
> f.bars  # SELECT * FROM bar WHERE foothing_id=1337
>
> Thus, a back-ref is limited to a single table. The example from
> @yanghg-basefx <https://github.com/yanghg-basefx> may work but is also
> inefficient in that it executes 2 queries and coerces to a list,
> potentially using a lot of memory if the result sets are large.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/coleifer/peewee/issues/1390#issuecomment-347218717>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AHwCh-MaJFVflz_OCxRDlei_7sqMiNdjks5s6tZjgaJpZM4QlNgA>
> .
>


Well the problem is that if you have two classes you'll end up with two separate tables. That makes sense, right? Depending on how you structure those tables, you could possibly use a UNION query or something, but you're quickly running into problems trying to conflate object-orientation with relational database design.