views:

35

answers:

1

My site has two types of users; customers and suppliers. I have ended up with the following class structure:

class Customer(models.Model):
    # stuff specific to customers

class Supplier(models.Model):
    # stuff specific to suppliers

class Profile(models.Model):  # returned by Django's User.get_profile()
    user = models.ForeignKey(User, unique=True)
    customer = models.OneToOneField(Customer, null=True, unique=True)
    supplier = models.OneToOneField(Supplier, null=True, unique=True)

Now I need to add multiple addresses to these models:

  • both customers and suppliers should have their "user" address, so should be in Profile
  • customers also have a billing address, should be in Customer then

Address would be something like:

class Address(models.Model):
    street1 = models.CharField(max_length=100)
    street2 = models.CharField(max_length=100)
    zipcode = models.CharField(max_length=16)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100)

I can see two straightforward solutions to re-use the address information: either refer to Address via ForeignKey from Profile & Customer classes, or inherit Profile & Customer classes from Address.

I can see some pros for both approaches:

ForeignKey

  • groups the address data nicely behind one field instead of "polluting" the model
  • no risk of multiple inheritance in future

Inheritance

  • easier access to fields
  • fewer database joins
  • addresses are automatically visible with the object in Django's admin

Which one would you go with and why? Do you think either of the solutions is inherently bad? Do you see some better alternatives?

+1  A: 

I would probably go with the Foreign Key approach - I think it's cleaner.

Dealing with the "pros" of inheritance you list:

  1. It's easy to access fields belonging to an object that is Foreign Keyed - my_customer.address.zipcode isn't too hard, is it?
  2. I doubt you'll find joins prohibitively expensive, and if you do you can always avoid them when fetching lots of Customers/Suppliers.
  3. You can always display addresses alongside the object in Django's admin if you define a __unicode__() method on Address, and just add address (if that's what you call the ForeignKey property of Customer) to your admin's list_display.
Dominic Rodger
With the admin aspect I was mostly
stalemate
Duh, still learning this stuff... :-) So: Good points! With the admin aspect I was mostly concerned about the object-level view. There it would be nice to see the address details blown open, not crammed up in one string. I guess this can be achieved with InlineModelAdmin, but still it's not as clean as with inheritance.
stalemate
You can always add parts of the address as columns in your admin - e.g. add `address.zipcode` to your admin's `list_display`.
Dominic Rodger