My problem:
I want my Customers to be able to connect many different Products to one Contract, and the code to list all Products attached to a Contract feels dirty.
My Models
class Contract(models.Model):
# The contract, a customer can have many contracts
customer = models.ForeignKey(Customer)
class Product(models.Model):
# A contract can have many different products
contract = models.ForeignKey(Contract)
start_fee = models.PositiveIntegerField()
# A customer may have ordered a Car, a Book and a HouseCleaning,
# 3 completly different Products
class Car(Product):
brand = models.CharField(max_length=32)
class Book(Product):
author = models.ForeignKey(Author)
class HouseCleaning(Product):
address = models.TextField()
To list all the products connected to a Contract, the code looks something like this:
c = Contract.objects.get(pk=1)
for product in c.product_set.all():
print product.book # Will raise an Exception if this product isnt a Book
I can't find any sane way to find out what kind of product a Product is!
My current solution
I've solved it like this... but this whole mess feels... wrong. I'd be happy for any pointers in the right direction.
class Product(models.Model):
# (as above + this method)
def getit(self):
current_module = sys.modules[__name__]
classes = [ obj for name, obj in inspect.getmembers(current_module)
if inspect.isclass(obj) and Product in obj.__bases__ ]
for prodclass in classes:
classname = prodclass.__name__.lower()
if hasattr(self, classname):
return getattr(self, classname)
raise Exception("No subproduct attached to Product")
So i can fetch each specific product like this (pseudo-ish code) :
c = Contract.objects.get(pk=1)
for product in c.product_set.all():
print product.getit()
to list all the "real" products, and not just the baseproduct instance.
What I need help with
Sugggestions to do this in some kind of sane way.
I don't mind having to abstract everything away a bunch of steps, just to get cleaner code.
This other stack question looks directly related -- maybe it will help?
>>> Product.objects.all()
[<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...]
Subclassed django models with integrated querysets
Specifically, the snippet has subclassed models Meal
Salad(Meal)
http://djangosnippets.org/snippets/1034/
Good luck!