pythondjangogeneric-foreign-keymulti-table-inheritance

Querying multiple Django models


I'm looking for some advice on how to execute a query against multiple objects and then use them together in a detail view for their related object. Here is what I'm working with right now:

-- app/models.py --

class Material(models.Model):
  created = models.DateTimeField(auto_now_add=True)
  updated = models.DateTimeField(auto_now=True)
  title = models.CharField(max_length=50)
  slug = models.SlugField()
  description = models.TextField()

  def __str__(self):
    return self.title

class Category(Material):
  parent = models.ForeignKey('self', related_name='children')

class Content(Material):
  author = models.ForeignKey(User)
  category = models.ForeignKey(Category)

class SomeObject(Content):
  # Model specific properties and methods

class SomeOtherObject(Content):
  # Model specific properties and methods

What I am trying to accomplish is to display both SomeObject and SomeOtherObject together in a Category detail view. Each of these models will have different attributes that make them both unique to each other. Is this a situation where the generic foreign keys are useful?

-- app/templates/category_detail.html --

{% block content %}
  <header class="category-header">
    <h1 class="category-title">{{ category.title }}</h1>
  </header><!-- .category-header -->

  <section class="category-items">
    {% for item in category.manager_that_queries_both.all %}
      # Display each item differently depending on the type
    {% empty %}
      "Oops, we couldn't find anything for this category!"
    {% endfor %}
  </section><!-- .category-items -->
{% endblock %}

I would like to stay away from hacks that are going to be difficult to maintain for the lifetime of this product if possible. Thanks again for your help guys =)


Solution

  • For the manager_that_queries_both.all You can use Django Model Utils.

    Specifically the Inheritance Manager.

    Your foreign keys would refer to the base class. and then you can query them with

    Material.objects.select_subclasses()
    

    To do things in your templates depending on the type of the object you could implement the filter described here.