Or
A) Use multiple table inheritance and create a base class "Eater" that inherits Cat, Cow and Human.
B) Use Generic Relation , where Food can be associated with any other model.
These are well-documented and officially supported features, you should stick with them to keep your own code clean, avoid workarounds, and be sure that it will continue to be supported in the future.
- EDIT (Aka "how to be a reputation whore")
So, here is the recipe for this particular case.
Suppose you absolutely want separate models for Cat, Cow and Human. In a real application, you want to ask yourself why the category field will not do the job.
It’s easier to get to the “real” class through general relationships, so here is an implementation for B. We cannot have this “food” field in Person, Cat or Cow, or we will face the same problem. Therefore, we will create an intermediate model "FoodConsumer". We will need to write additional validation checks if we do not want more than one product per instance.
from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic class Food(models.Model): """Food, by name.""" name = models.CharField(max_length=25)
Now, to demonstrate this, simply write this working doctest :
""" >>> from models import * Create some food records >>> weed = Food(name="weed") >>> weed.save() >>> burger = Food(name="burger") >>> burger.save() >>> pet_food = Food(name="Pet food") >>> pet_food.save() John the farmer likes burgers >>> john = Person(first_name="John", last_name="Farmer", birth_date="1960-10-12") >>> john.save() >>> john.foods.create(food=burger) <ConsumedFood: ConsumedFood object> Wilma the cow eats weed >>> wilma = Cow(farmer=john) >>> wilma.save() >>> wilma.foods.create(food=weed) <ConsumedFood: ConsumedFood object> Felix the cat likes pet food >>> felix = Cat(name="felix") >>> felix.save() >>> pet_food.eaters.create(eaten_by=felix) <ConsumedFood: ConsumedFood object> What food john likes again ? >>> john.foods.all()[0].food.name u'burger' Who getting pet food ? >>> living_thing = pet_food.eaters.all()[0].eaten_by >>> isinstance(living_thing,Cow) False >>> isinstance(living_thing,Cat) True John farm is in fire ! He looses his cow. >>> wilma.delete() John is a lot poorer right now >>> john.foods.clear() >>> john.foods.create(food=pet_food) <ConsumedFood: ConsumedFood object> Who eating pet food now ? >>> for consumed_food in pet_food.eaters.all(): ... consumed_food.eaten_by <Cat: Cat object> <Person: Person object> Get the second pet food eater >>> living_thing = pet_food.eaters.all()[1].eaten_by Try to find if it a person and reveal his name >>> if isinstance(living_thing,Person): living_thing.first_name u'John' """