要麼
A)使用multiple table inheritance,並創建一個 「食」 的基類,即貓,牛和人繼承。 B)使用Generic Relation,其中Food可以鏈接到任何其他模型。
這些都是有據可查的和官方支持的功能,您最好堅持讓它們保持自己的代碼清潔,避免變通方法並確保將來仍然支持它。
- EDIT(又名「如何成爲一個聲譽妓女」)
所以,這裏是特定情況下的配方。
讓我們假設你絕對需要貓,牛和人的單獨模型。在現實世界的應用程序中,您想問自己爲什麼「類別」字段不能完成這項工作。
通過泛型關係可以更容易地到達「真實」類,所以這裏是B的實現。我們不能在Person,Cat或Cow中擁有這個'food'字段,否則我們會遇到同樣的問題。因此,我們將創建一箇中間人「FoodConsumer」模型。如果我們不想爲一個實例提供超過一種食物,我們將不得不編寫額外的驗證測試。現在
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)
# ConsumedFood has a foreign key to Food, and a "eaten_by" generic relation
class ConsumedFood(models.Model):
food = models.ForeignKey(Food, related_name="eaters")
content_type = models.ForeignKey(ContentType, null=True)
object_id = models.PositiveIntegerField(null=True)
eaten_by = generic.GenericForeignKey('content_type', 'object_id')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
foods = generic.GenericRelation(ConsumedFood)
class Cat(models.Model):
name = models.CharField(max_length=50)
foods = generic.GenericRelation(ConsumedFood)
class Cow(models.Model):
farmer = models.ForeignKey(Person)
foods = generic.GenericRelation(ConsumedFood)
,以證明它讓我們只寫了這方面的工作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's getting pet food ?
>>> living_thing = pet_food.eaters.all()[0].eaten_by
>>> isinstance(living_thing,Cow)
False
>>> isinstance(living_thing,Cat)
True
John's 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's 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's a person and reveal his name
>>> if isinstance(living_thing,Person): living_thing.first_name
u'John'
"""
嗨文森特,爲響應感謝。如何正確使用MTI或GR來回答這個問題將非常感謝:)。 – 2008-11-11 17:14:09