class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField()
parent = models.OneToOne(Place)
which means normal rules apply you should be able to do this
place = new Place.objects.get(pk=1)
restaurant = place.restaurant
if restaurant isn't defined in your place then place isn't a restaurant.
I'd imagine you prolly have something more sophisticated like:
Place()
Restaurant(Place)
Theater(Place)
CrackHouse(Place)
Which could make life interesting depending on what you're doing...
I'd imagine some tricky if else or try/except statments would help you
figure out which class your child is. Somebody smarter than I would
have to help you with that.
Vance
--
To pretend, I actually do the thing: I have therefore only pretended to pretend.
- Jacques Derrida
You're assuming the current behavioural restrictions are imposed by
Python. They're not. They exist because we are providing a Python
representation of rows from a relational database. There's no direct
equivalent to SQL table-like inheritance in Python because if you
subclass a model, all instances look like the appropriate child class.
That isn't true at the database level (which is more like C/C++-style
inheritance). The difference is, though, that in C++, instantiation can
add extra stuff into the in-memory representation whereas we cannot add
extra stuff to the database to change things we may not own.
[...]
> My solution would be to add an automatically generated field called
> concrete_content_type or something that is automatically added to
> every model, that way it would be possible to know which type to
> instantiate when you do a query on the superclass table, problem is
> that this would break existing django apps.
More importantly, it would make it impossible to subclass third-paty
models, which is why we don't do this. Changing somebody else's database
table just because you are subclassing it is bad form. You may not even
have the necessary database permissions to do so in all cases (e.g.
multiple database cases).
For situations where you are creating all the models in the hierarchy
and if your situation requires querying the base object to descend to
the children, then you should definitely add a type field. It's the
natural way to do things if you're wanting to implement this as
inheritance. On the other hand, you may just prefer to be explicit and
not represent that situation as inheritance at all: simply use
one-to-one fields so that your code accurately reflects what is going on
at the data storage level. Django allows both approaches, so pick
whichever methods suits you taste best.
Regards,
Malcolm
I'm not thinking you're hostile, fear not. Just trying to point you in
the right direction as far as developing an intuition about why things
behave and are implemented in this particular fashion. You're asking a
question that's been asked and answered on this list before (but this
list is of high enough volume that finding that stuff can require a bit
of searching, so I don't mind periodic repetition).
Model inheritance for the persistence layer isn't likely to have really
broad uses, primarily because object-oriented data structures don't mix
well with relational databases (search for "vietnam of computer science"
when you have a spare evening some time). All it's really intended for
is to provide a convenient way to extend third-party models. Usually the
answer to "should I use model inheritance for..." is "no". Just use
explicit one-to-one relations so that things are clear. Sometimes it's a
sufficient time-saver to warrant usage, but the really common use-case
seems to be abstract base classes as a way of factoring out common data,
not querying base classes and then narrowing the results to the
descendents (which is still possible, but you either have to use extra
queries or set your models up appropriately in the first place).
We did discuss requiring an extra column on every table to support this,
but decided it wasn't a good idea. It isn't necessarily the common case
(it's always difficult to determine what *is* a really common, but this
isn't a normal use of relational data structures, which is the guiding
factor) and it is an extra column that's needed everywhere, even on
tables that aren't subclassed. This isn't a trivial point because if
you're using this mode of operation regularly, that column should be
indexed to speed up joins, but if you're not using it, the extra index
is just a performance drag on inserts. Having everybody pay the
performance penalty no matter what their data size or usage patterns was
something we decided against.
Regards,
Malcolm