views:

15

answers:

1

Hello Stacker's & Django-ists,

I'm looking for some validation on a subclassing approach. I have the following:

class Person(models.Model):
    """
    Basic person
    """
    user = models.ForeignKey(User) # hide
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(blank=True, max_length=200)

    class Meta:
        verbose_name_plural = "People"

    def __unicode__(self):
        return u"%s, (%s)" % (self.first_name, self.user)


class Contributor(Person):
    """
    Contributor
        A Core contributor of the site content workflow
    """

    class Meta:
        verbose_name = 'contributor'
        verbose_name_plural = 'contributors'

    def get_articles(self):
        """
        Return the articles that the author has published.
        """
        return Article.objects.filter(self_in=authors)

class Member(Person):
    """
    Member

        A Member of the website.
    """

    # Member history, payments etc...
    joined = models.DateTimeField()

So, each Member or Contributor is a Person within the system, but it is possible for a Person to be 'None', 1 or both Member & Contributor, depending on their context.

This subclassing approach makes it simple to do things like:

#...
contributors = models.ManyToManyField(Contributor, help_text="Contributors/Authors to this article")

or

print Member.objects.all()

... and of course the usual efficiencies of subclassing, i.e. common fields and methods.

However, I'm wondering about the pros & cons of doing something like

class Person(models.Model):
    """
        Person
        """
        user = models.ForeignKey(User) # hide
        first_name = models.CharField(max_length=200)
        last_name = models.CharField(blank=True, max_length=200)
        is_contributor = models.BooleanField()
        is_member = models.BooleanField()

but then needing to filter things like

# Assuming this is possible...
contributors = models.ManyToManyField(Person.objects.filter(is_contributor=True), help_text="Contributors/Authors to this article")

With the subclassing approach, I wonder about the challenges of being aware of users that are People (Person), Members or Contributors - and being able to discern between.

i.e. its really easy to do if person.is_contributor: but perhaps more challenging

try:
    Contributor.objects.get(person__user_id=request.user.id)
except:
    no_access()
else:
    let_them_in()

Apologies for the open-endness of this question -- it may have been more an opportunity to think out aloud.

Answers appreciated.

A: 

First, there are two oddities about your model to begin with:

1) Why is Person -=> User a ForeignKey and not a OneToOne? Might a user be more than one person?

2) User already has first and last names - why also assign them to person?

Next, to the extent that your ultimate goal is the authorization depicted at the end, why not just use permissions? Then you won't need the boolean fields or the try - except at the end.

Fundamentally, I see nothing wrong with subclassing the User model. Folks in #django often fight over this, but if done right, it is one of the most time-saving and powerful steps you can take when you first sit down with your new django project.

Adding different subclasses of User with different attributes and different methods can very quickly give you a robust user environment with enormous auth possibilities. Thus far, however, it doesn't look like you have done anything that requires you to subclass User.

Justin Myles Holmes