Model Inheritance in qsrf and User?

6 views
Skip to first unread message

Rob Hudson

unread,
Apr 24, 2008, 12:16:14 AM4/24/08
to Django developers
I don't know if this should go to devs or users but I wanted to ask...

Now that queryset-refactor has implemented model inheritance (and will
soon be in trunk), will the recommended way to tie in new columns to
contrib.auth.models.User change? For example, if we want to add in
profile information specific to our apps?

Thanks,
Rob

James Bennett

unread,
Apr 24, 2008, 12:38:06 PM4/24/08
to django-d...@googlegroups.com
On Wed, Apr 23, 2008 at 11:16 PM, Rob Hudson <trebor...@gmail.com> wrote:
> Now that queryset-refactor has implemented model inheritance (and will
> soon be in trunk), will the recommended way to tie in new columns to
> contrib.auth.models.User change? For example, if we want to add in
> profile information specific to our apps?

Well, I personally have been saying for over a year that inheritance
has never been and never will be the right way to do that, so I think
y'all know what my answer is...


--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

AmanKow

unread,
Apr 25, 2008, 11:23:18 AM4/25/08
to Django developers
> Well, I personally have been saying for over a year that inheritance
> has never been and never will be the right way to do that, so I think
> y'all know what my answer is...

Could you elaborate or point to elaboration on why non-abstract
inheritance is a bad fit for extending user?
Thanks!

Rajeev J Sebastian

unread,
Apr 25, 2008, 2:13:50 PM4/25/08
to django-d...@googlegroups.com

Because every app has its own concept/method of how to link info to a
User object, hence that information is best held in other models each
with a FK to the User.

Regards
Rajeev J Sebastian

James Bennett

unread,
Apr 25, 2008, 2:26:28 PM4/25/08
to django-d...@googlegroups.com
On Fri, Apr 25, 2008 at 10:23 AM, AmanKow <wwe...@si.rr.com> wrote:
> Could you elaborate or point to elaboration on why non-abstract
> inheritance is a bad fit for extending user?

http://www.b-list.org/weblog/2007/feb/20/about-model-subclassing/

flo...@gmail.com

unread,
Apr 25, 2008, 2:39:42 PM4/25/08
to Django developers
The multi-table inheritance stuff in queryset-refactor does
essentially what is mentioned in that article, except it merges the
namespace so that it's easier to use. That being said, it seems that
OneToOneField has been improved as well, for those who want to be
explicit about that link.

On Apr 25, 1:26 pm, "James Bennett" <ubernost...@gmail.com> wrote:

AmanKow

unread,
Apr 25, 2008, 3:06:40 PM4/25/08
to Django developers
Hmmm... I read the subclassing post. As a non-abstract child is
essentially a one to one with some syntactical sweetness, I'm still
not sure how using a one to one field is better suited than
inheritance for extending user.

Rajeev J Sebastion wrote:
> Because every app has its own concept/method of how to link info to a
> User object, hence that information is best held in other models each
> with a FK to the User.

Don't see why each model can't do what they want... one to one,
inheritance, etc to obtain the same result.

Seeking enlightenment as I try to prepare my mind for qsrf

Ian Kelly

unread,
Apr 25, 2008, 3:26:29 PM4/25/08
to django-d...@googlegroups.com
On Fri, Apr 25, 2008 at 1:06 PM, AmanKow <wwe...@si.rr.com> wrote:
>
> Hmmm... I read the subclassing post. As a non-abstract child is
> essentially a one to one with some syntactical sweetness, I'm still
> not sure how using a one to one field is better suited than
> inheritance for extending user.

Purely in terms of OO design, because it's cleaner. Object
composition is usually a more appropriate paradigm than class
inheritance. To take the example from the post that started this
thread, the relationship between users and user profiles is "has-a",
not "is-a". So what would be the design benefit of applying
inheritance here in the first place?

Marty Alchin

unread,
Apr 25, 2008, 3:40:59 PM4/25/08
to django-d...@googlegroups.com
On Fri, Apr 25, 2008 at 3:26 PM, Ian Kelly <ian.g...@gmail.com> wrote:
> Purely in terms of OO design, because it's cleaner. Object
> composition is usually a more appropriate paradigm than class
> inheritance. To take the example from the post that started this
> thread, the relationship between users and user profiles is "has-a",
> not "is-a". So what would be the design benefit of applying
> inheritance here in the first place?

Not to get too much into this discussion, but I tend to be slow to
understand design patterns and other paradigms. What then would be the
appropriate way to handle an app that managed authors? I can see two
possibilities:

class Author(User):
pen_name = models.CharField(max_length=255)

or

class AuthorProfile(models.Model):
user = models.OneToOneField(User)
pen_name = models.CharField(max_length=255)

Essentially, whether it has the semantics of an "is-a" or a "has-a"
relationship seems to depend solely on what name I give the class.
Clearly a user could "be an" author, while he/she could instead "have
an" author profile.

How would I proceed in a situation like this?

-Gul

peschler

unread,
Apr 27, 2008, 6:29:14 PM4/27/08
to Django developers
On 25 Apr., 21:40, "Marty Alchin" <gulop...@gamemusic.org> wrote:
>
> Not to get too much into this discussion, but I tend to be slow to
> understand design patterns and other paradigms. What then would be the
> appropriate way to handle an app that managed authors? I can see two
> possibilities:
>
> class Author(User):
> pen_name = models.CharField(max_length=255)
>
> or
>
> class AuthorProfile(models.Model):
> user = models.OneToOneField(User)
> pen_name = models.CharField(max_length=255)
>
> Essentially, whether it has the semantics of an "is-a" or a "has-a"
> relationship seems to depend solely on what name I give the class.
> Clearly a user could "be an" author, while he/she could instead "have
> an" author profile.
>
> How would I proceed in a situation like this?

I would tend to subclassing in this case. To make my point clear add
another user model called "Reader" to the example:

class Reader(User):
stories_read = models.IntField()

Assuming that only author's should have a "pen_name" and only readers
should have a "stories_read" field, it would be feeling "not
naturally" to put these fields in a profile (and therefore go the
profile way).

Furthermore assuming that your site requires *every* user (readers and
authors) to specify their phonenumber (which is not part of standard
User model), this should go into a profile:

class UserProfile():
user = models.OneToOneField(User)
phone = models.PhoneField()

That way you benefit from both. You have Authors and Readers which are
users ("is-a"), and which both have a phone number ("has-a").
From an OO standpoint you are now able to use Authors and Readers
instances, whereever a User instance is used in the API. This is not
possible when using a profile.

Please be aware that I did not test the qsrf branch and the examples
above and the way I understand things are maybe not how things work.

peschler

michaelg

unread,
Apr 30, 2008, 1:59:57 PM4/30/08
to Django developers
I just started learning about extending Django's User model, so bear
with me as I make sure I understand these things correctly. So we can
subclass the User class doing something like:

class Reader(User):
fields...

class Author(User):
fields...

Does this mean that any new instance of Reader or Author will also be
found in User (or some reference to Reader and Author)? I understood
this to be the case based on peschler's UserProfile class:

class UserProfile():
user = models.OneToOneField(User)
fields...

So this will allow you to create a universal UserProfile class for
Readers and Authors as opposed to doing something like:

class AuthorProfile():
user = models.OnetoOneField(Author)
fields...

class ReaderProfile():
user = models.OnetoOneField(Reader)
fields...

Also, what's the difference between OnetoOneField and ForeignKey?
Does it make a difference which one you use? Thanks in advance for
your help.

michael

Rajeev J Sebastian

unread,
Apr 30, 2008, 2:17:04 PM4/30/08
to django-d...@googlegroups.com
On Mon, Apr 28, 2008 at 3:59 AM, peschler <pesc...@googlemail.com> wrote:
>
> On 25 Apr., 21:40, "Marty Alchin" <gulop...@gamemusic.org> wrote:
> >
> > Not to get too much into this discussion, but I tend to be slow to
> > understand design patterns and other paradigms. What then would be the
> > appropriate way to handle an app that managed authors? I can see two
> > possibilities:
> >
> > class Author(User):
> > pen_name = models.CharField(max_length=255)
> >
> > or
> >
> > class AuthorProfile(models.Model):
> > user = models.OneToOneField(User)
> > pen_name = models.CharField(max_length=255)
> >
> > Essentially, whether it has the semantics of an "is-a" or a "has-a"
> > relationship seems to depend solely on what name I give the class.
> > Clearly a user could "be an" author, while he/she could instead "have
> > an" author profile.
> >
> > How would I proceed in a situation like this?
>
> I would tend to subclassing in this case. To make my point clear add
> another user model called "Reader" to the example:

The main problem with this approach is multiple apps. For e.g., a site
may have a CMS, a blog, a forum, etc ... and if each app were to
subclass User .....

you get the picture. Thats why User should never be subclassed (for
this kind of purpose anyway). In fact, I would so far as to say "never
use inheritance, unless you really know what you are doing". of
course, Inheritance being the first thing people teach about OO doesnt
help at all.

regards
Rajeev J Sebastian

michaelg

unread,
Apr 30, 2008, 2:33:02 PM4/30/08
to Django developers
Rajeev,

How, then, would you suggest handling multiple user groups? To
continue with a similar theme from above, let's say we had two user
groups, Authors and Publishers. When signing up, an Author might need
to input their first name, last name, email, and a password, but a
Publisher would only need their publisher name, password, and maybe an
email. We'd have to use a different signup forms to allow for the
differences in first and last name, and publisher name. After
creating an account, an Author might add profile information that is
unique to Authors, and a Publisher might add profile that is unique to
Publishers. Is this still not a candidate for subclassing? Are you
suggesting that all information just be stored in the profile
(including email, password, etc.)? Thanks for helping!

michael

On Apr 30, 11:17 am, "Rajeev J Sebastian" <rajeev.sebast...@gmail.com>
wrote:

George Vilches

unread,
Apr 30, 2008, 2:35:46 PM4/30/08
to django-d...@googlegroups.com

On Apr 25, 2008, at 3:40 PM, Marty Alchin wrote:

> *snip*


> class AuthorProfile(models.Model):
> user = models.OneToOneField(User)
> pen_name = models.CharField(max_length=255)

Now that QSRF has landed, this type of thinking leads me to: who's
working on 121-rewrite? And more importantly, can I offer my
assistance? :)

Things like this would be well served by being able to follow a
OneToOneField in both directions via a .select_related() (no extra
trip to the DB). We have several use cases, among them our own User
system based on django.contrib.auth, in which we currently use almost
exactly what you see above as our "extended profile" that would be
very useful to have the relationship work in both directions in queries.

I will hesitantly say too, *if* OneToOneFields were to work that way
and only generate a single query no matter which way they were
approached (and followed all the proper ForeignKeys on both sides), I
think it would end a good portion of the confusion/arguments about the
proper design patterns to use here, since the only major justification
left for not using the 121 mechanism would be on the saving side at
that point.

gav

Tai Lee

unread,
May 1, 2008, 10:19:55 AM5/1/08
to Django developers
> Purely in terms of OO design, because it's cleaner.  Object
> composition is usually a more appropriate paradigm than class
> inheritance.  To take the example from the post that started this
> thread, the relationship between users and user profiles is "has-a",
> not "is-a".  So what would be the design benefit of applying
> inheritance here in the first place?

I think whether it is a "has-a" or "is-a" relationship depends on the
developer and the application. There's no reason for a developer not
to extend User and reference their own User model instead of django's,
if it makes more sense to them. Why make Profile models all over the
place when you can just make User models and have all the syntactic
sugar that comes with it, being able to treat it as a single entity?

flo...@gmail.com

unread,
May 1, 2008, 11:49:27 AM5/1/08
to Django developers
> Now that QSRF has landed, this type of thinking leads me to: who's  
> working on 121-rewrite?

I'm fairly certain that in refactoring QuerySet, OneToOneField has
been fixed. It's the base mechanism that allows multi-table
subclassing to work, in fact.

George Vilches

unread,
May 1, 2008, 12:15:12 PM5/1/08
to django-d...@googlegroups.com

I do not believe you understood what I mean by fixed. OneToOneField
has always worked, halfway. What it doesn't do is follow the
relationship in both directions:

from django.db import models

class A(models.Model):
a1 = models.CharField(max_length=20)

class B(models.Model):
b1 = models.CharField(max_length=20)
b2 = models.OneToOneField(A)


B.objects.select_related() creates this query (MySQL, taken from the
logs):

SELECT `t1_b`.`id`, `t1_b`.`b1`, `t1_b`.`b2_id`, `t1_a`.`id`,
`t1_a`.`a1` FROM `t1_b` INNER JOIN `t1_a` ON (`t1_b`.`b2_id` =
`t1_a`.`id`)

A.objects.select_related() creates this query:

SELECT `t1_a`.`id`, `t1_a`.`a1` FROM `t1_a`


A complete OneToOneField would generate effectively the same query in
both directions, since it's a special type of ForeignKey that the
reverse relationship makes sense to automatically select on.

If this worked, then in the User case, you could select_related() on
the UserProfile, *OR* .select_related() on the User(), and you would
get the same data either way, no matter how many models were connected
via OneToOneField in this manner. I would assume that all the
normal .select_related(***) options would work as well across this,
like "depth" and the new options for picking a subset of fields only
to follow the relations on.

(As an aside, forward FKs on both sides of the OneToOne should be
followed, but that I would assume is an incidental of getting
OneToOnes working this way in the first place).

Does that make more sense as to why it would alleviate the issue?

Thanks,
gav

Reply all
Reply to author
Forward
0 new messages