views:

64

answers:

2

What is the appropriate way to create an instance of the following two models

class Administrator(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    account = models.ForeignKey(Account)

class Account(models.Model):
    owner = models.OneToOneField(Administrator)

Both require each other. An account cannot exist without a primary user (owner), and an administrator (which is what owner is) cannot exist without an account. Yes a general User object can exist on it's own but I can't wrap my brain around which of these should come first and how to implement that correctly. If I have to use blank=True on Administrator's account attribute I will, but is there a better way? Should I use a transaction to ensure one cannot exist without the other?

+3  A: 

If two models exist such that each requires the other, they should usually be combined into a single model.

In any case there is probably a better way to structure the classes. Personally I would construct a UserProfile class as follows:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    administrator = models.BooleanField()

or possibly:

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

class AdministratorProfile(UserProfile):
    # attributes

or even:

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

class AdministratorProfile(models.Model):
    profile = models.OneToOneField(UserProfile)

any of these methods should work.

Marcus Whybrow
+1 for the use of a user profile (for which Django has built-in support now).
jathanism
ah yes and then add `AUTH_PROFILE_MODULE = 'appname.UserProfile'` to your settings file to enable calling of `get_profile()` on User instances.
Marcus Whybrow
You're right. Thanks for all the answers today :) I think this way (second or third example) is the best because it's extensible. One thing though. Why didn't you just subclass User with UserProfile in example 2?
orokusaki
The `UserProfile` database table would have lots of columns from the `User` model, and the original `User` model (and table) would not be used. I prefer not to extend from models I did not write for this very reason. There are other subtle changes and I prefer maintaining the encapsulation of the existing object, and my own.Although there are benefits to keeping everything in one table and one model, reducing database reads I would have though is one of them. And no problem with the answers today, any time.
Marcus Whybrow
A: 

I'm not totally sure I fully understand the differences between Administrator, Account, and contrib.auth.User,

This feels like the is-a vs has-a discussion. It sounds like Administrator is a User (really, a UserProfile, for reasons peculiar to django), and Administrator has an Account. Accounts do not have anything, since they cannot both own and be owned.

This is like a bank account vs a bank customer. Bank customers own their accounts, not the other way around. On the other hand, bank accounts have a list, and that list is the bank customers that may use the account.

TokenMacGuy