Roy Prins
Roy Prins

Reputation: 3080

Effectively use Multi-table inheritance (one-to-one relationships)

I need several models that inherit from a base class in a one-to-one relationship. In keeping with the Django example:

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

class Garage(Place):
    car_brands_serviced = Models.ManyToManyField(Brands)

class Boutique(Place):
    for = Models.ChoiceField(choices=( ("m", "men"), ("w", "women"), ("k","kids"))

# etc

Now how do I effectively distinguish between the various types of Places when I iterated them in a template (or view function)? Right now, I only see this solution (if I want to iterate over Places, rather than child models individually):

for place in Place.objects.all():
    try:
        r = place.restaurant
        # Do restaurant stuff here
    except ObjectDoesNotExist:
        try:
            g = place.garage
            # Do garage stuff here
        except ObjectDoesNotExist:
            try:
                b = place.boutique
                # Do boutique stuff here
            except ObjectDoesNotExist:
                # Place is not specified

Not even sure how that would translate to a template, but this code seems very wrong and inefficient.

As an escape, I guess you could make a choicefield in Place to track which child model is related, but that equates to dangerous denormalisation.

Am I somehow overthinking this? How do you do this?

Upvotes: 0

Views: 317

Answers (1)

Jeremy S.
Jeremy S.

Reputation: 1126

Could it be something simple like:

models.py:

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)
    is_restaurant = True

class Garage(Place):
    car_brands_serviced = Models.ManyToManyField(Brands)
    is_garage = True

A template could work like this – template.html:

{% for place in places %}
 {% if place.is_restaurant %}
  <!-- Restaurant Stuff -->
 {% elif place.is_garage %}
  <!-- Garage Stuff -->
 {% endif %}
{% endfor %}

Upvotes: 1

Related Questions