How can I create categories and subcategories in django models?

I am building a simple website for a car marketplace. I have written the brand, series and car models. (I purposefully want to treat each of them as seperate models.) Whenever I create a car in the admin panel I want to be able to pick a car brand - let's say Mercedes - and when I choose the brand I want the next option to be only the series of Mercedes not the series of other cars.

Here is a representation of my code so far:

class Brand(models.Model):
    brand = models.CharField(max_length=100)

class Series(models.Model):
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    series = models.CharField(max_length=100)

class Car(models.Model):
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    series = models.ForeignKey(Series, on_delete=models.CASCADE)

Use a ChainedForeignKey [readthedocs.io] instead from the django-smart-selects package [readthedocs.io]:

from smart_selects.db_fields import ChainedForeignKey


class Car(models.Model):
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    series = ChainedForeignKey(
        Series,
        chained_field='brand',
        chained_model_field='brand',
        show_all=False,
        on_delete=models.CASCADE,
    )

Sounds like you have a brief idea of your model hierarchy but just need to implement it. This is something Django does out of the box, you shouldn't need a 3rd party package to maintain this.

Start by reading about models in Django, especially Primary and Secondary/Foreign keys.

You will link each subsequent model through a foreign key to the primary model using a many-to-many mapping. Set your main primary key as the car (at the bottom level). Given it's a marketplace, set something like a UUID or BigInt as this unique ID as you will likely have a lot of values.

I would skip the junction tables approach and just create a linkage in your models, something like this:

class cars(models.Model):
    name = models.CharField(max_length=100)
    series = models.ManyToManyField("series", related_name="cars", blank=True)
    brand = models.ManyToManyField("brand", related_name="cars", blank=True)

class series(models.Model):
    your model here


class brand(models.Model):
    your model here

Then you can surface this in your Django admin and create relations there. Eventually you can surface this to the end user in custom css/html and allow selections.

Back to Top