Django Sharing One Model Between Two Others
Solution 1:
I think Generic Foreign Key is the answer. Something like:
from django.dbimport models
from django.contrib.contenttypes.fieldsimportGenericForeignKeyfrom django.contrib.contenttypes.modelsimportContentTypeclassProduct(models.Model):
...
classFood(Product):
...
classWine(Product):
...
classReview(models.Model):
...
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
This allows us to relate a review to any single record of any model in our project. The content_type
field tracks which model you are trying to relate to (Food
or Wine
in this case). The object_id
field track which record in the Wine
or Food
table we are trying to track. content_object
is a convenience attribute that allows us direct access to the object (once the review has been saved).
When creating a new review you just assign the Wine
or Food
to the content_object
field:
wine = Wine.objects.get(...)
review = Review(..., content_object=wine)
review.save()
Solution 2:
You could also use Multi-table inheritance instead of an AbstractClass
for Item
. Then you can set a direct ForeignKey
to Item
in Review
.
You can also combine this with InheritanceManager
:
from model_utils.managers import InheritanceManager
classItem(models.Model):
name = models.CharField(max_length=30)
desc = models.CharField(blank=True,max_length=100)
objects = InheritanceManager()
classWine(Item):
wine_type = models.ForeignKey(WineType)
wine_year = models.IntegerField( choices=YEAR_CHOICES, default=datetime.datetime.now().year)
source = models.ForeignKey(WineSource)
def__str__(self):
return self.source.name +' '+self.name+ ' ' + str(self.wine_type)+ ' '+ str(self.wine_year)
classFood(Item):
source = models.ForeignKey(FoodSource)
def__str__(self):
return self.source.name +' - '+self.name
classReview(models.Model):
rating = models.CharField(max_length=30)
value = models.CharField(max_length=30)
date = models.DateField(auto_now_add=True)
person = models.ForeignKey(Person)
item = models.ForeignKey(Item,null=True)
classMeta():
ordering = ['-date']
Then you can filter like this:
wine_reviews = Review.objects.exclude(item__wine__isnull=True)
food_reviews = Review.objects.exclude(item__food__isnull=True)
# and all item (directly sub-classed as wine or food:items = Item.objects.select_subclasses().all()
Post a Comment for "Django Sharing One Model Between Two Others"