marco.santonocito
marco.santonocito

Reputation: 1713

Django - Model with more than two foreign keys

I want to give a classification to every recipe and I need 3 levels (subject -> category -> subcategory). I have the following models:

class Recipe(models.Model):
    content = HTMLField()
    ...

class Subject(models.Model):
    name = models.CharField()

class Category(models.Model):
    subject = models.ForeignKey(Subject)
    name = models.CharField()

class Subcategory(models.Model):
    category = models.ForeignKey(Category)
    name = models.CharField()

Initially I was thinking to add a ForeignKey to the Recipe model, something like:

subcategory = models.ForeignKey(Subcategory)

So I could be able to go from the subcategory to the subject, doing a simple join.

But maybe is better to create a new table to improve performance and to have a scalable system, this is my thought:

class Classification(models.Model):
   recipe = models.ForeignKey(Recipe)
   subject = models.ForeignKey(Subject)
   category = models.ForeignKey(Category)
   subcategory = models.ForeignKey(Subcategory)

Using this last solution, I want to select the subcategory from the Recipe admin panel and then automatically fill the other fields (category and subject). My question is: how can I do that?

Thank you!

Upvotes: 0

Views: 185

Answers (2)

phoenix
phoenix

Reputation: 235

The classes Subject, Category, Subcategory and Recipe (with ForeignKey) creates fully normalized database design adding Classification is a part of denormalizing database (for example for performance issues).

Answering your question:

recipe = Recipe.objects.get(pk=1) # just assume that you have object instance under recipe
r_subcategory = recipe.subcategory
r_category = r_subcategory.category
r_subject = r_category.subject
new_classification = Classification(subject=r_subject, category=r_category, subcategory=r_subcategory, recipe=recipe)
new_classification.save()

I would really like to know if there is a way to create it in one database request (I could easily produce sql request for that, but I do not know how to achieve the same with Django ORM)

Upvotes: 1

arocks
arocks

Reputation: 2882

Your first design is actually the best. It is a completely denormalized database design. The second design has the possibility of putting your recipe in a subcategory unrelated to your category which is unrelated to your subject. So, what you gain in performance might be lost in data integrity.

Upvotes: 2

Related Questions