16

I am working on a Django application which contains an Offer model. An Offer instance contains the pricing conditions and points to a product definition. The product model is actually a hierarchy (I have a Television model, a Camcorder model, etc.). So I would like the Offer model to contain a polymorphic (or "generic") association to point to any product.

For now, all I have found is this to use the generic associations in the ContentTypes application. This might do, but I am looking for alternatives, if any.

Thanks for your help.

(one solution per answer please)

vishes_shell
  • 22,409
  • 6
  • 71
  • 81
MiniQuark
  • 46,633
  • 36
  • 147
  • 183

5 Answers5

6

ContentTypes is the right approach. This is because the ForignKey can only point to one type of table so you need to pass through the an intermediate table and do your split depending on the different type.

So model inheritance for the class hierarchy, but ContentType for the foreign keys.

ivan
  • 328
  • 4
  • 7
3

If you only need to point to "any product," not any model, then the solution is to have a Product model that all products inherit from (i.e. Television and Camcorder are both subclasses of Product), and give your Offer model a ForeignKey to Product.

Carl Meyer
  • 122,012
  • 20
  • 106
  • 116
  • 1
    Yes, this is the general idea, but if I do only that, then I have 2 drawbacks: firstly, I cannot use multiple-table inheritance, secondly when I go from an offer to a product, I get a Product instance instead of a Camcorder (or other concrete class) instance. – MiniQuark Jan 07 '09 at 09:16
  • 2
    You can automatically transform a Product instance into an (e.g.) Camcorder instance if you store an FK to the "child" ContentType (Camcorder) at creation time. More discussion at http://groups.google.com/group/django-users/browse_thread/thread/f4241bc16455f92d/7268c3f7bca6b046?lnk=raot – Carl Meyer Jan 10 '09 at 22:49
  • What do you mean by "I cannot use multiple-table inheritance"? Multiple-table inheritance is how Django implements inheritance from non-abstract base classes (unlike Rails, which does single-table inheritance). Your choices here are inheritance or generic relations; there's no other silver bullet. – Carl Meyer Jan 10 '09 at 22:53
3

You can't do that in Django. Either use generic relations or a Django app that add this feature like django_polymorphic.

Bite code
  • 578,959
  • 113
  • 301
  • 329
2

Take a look at django-polymorphic, this implements this feature, and also uses ContentTypes internally.

vdboor
  • 21,914
  • 12
  • 83
  • 96
-4

You might want to have a look at model inheritance.

sul4bh
  • 636
  • 8
  • 21
Guillaume
  • 18,494
  • 8
  • 53
  • 74
  • I obviously agree, but could you please spell out the answer to make it truly useful to someone that would be asking it. That way I can +1 it. – Ivan Jan 06 '09 at 14:29
  • Thanks, but I don't think this is the answer. What I need is to have something like: class Offer(models.Model): product = models.ForeignKey(Product) ... Where Product is an abstract class, and the actual referenced object is an instance of a concrete subclass. Any ideas? – MiniQuark Jan 07 '09 at 09:12