[Answer]-Field with inner structure in Django

1đź‘Ť

âś…

One approach would be to create a “main” table with all the common properties and separate tables for each type of object. This is very easy to do in Django and model definitions look “clean”, see Multi-table inheritance for details.

Example models for your situation:

# Hold common fields/properties
class Item(models.Model):
    type = ...
    price = ...
    weight = ...
    width = ...
    height = ...
    ...

# Below are example classes which will inherit all properties from Item
class CPU(Item):
    frequency = ...
    core_count = ...
    socket = ...

class Smartphone(Item):
    os = ...
    display_size = ...
    cpu = models.ForeignKey(CPU, ...)  # Example linking between items.

Note that each “concrete” item consists of two database rows: the common table and in the “concrete” table. The two tables are joined by a one to one field in the “concrete” table (Django adds this field for you, but you can redefine it, if you want).

Example methods of retrieving items from database:

# Get all "base" items without touching type tables
Item.objects.all()

# Get all items along with their child properties. This is rather ugly and expensive.
Item.objects.select_related('cpu', 'smarthphone', ...).all()

# Gets smartphones, uses a join to retrieve data from two tables.
# I don't remeber if the `select_related` is required here.
Smartphone.objects.select_related('item').all()  

# When type of the item is only know at runtime, you can query like this (requires additional table column for storing type):
Item.objects.filter(type='smartphone')
# Or alternatively finding out which type class you want.

Advantages:

  1. Class definitions look clean and simple.
  2. Very close to optimal database structure.
  3. One db query can retrieve items of various types.

Disadvantages:

  1. Excessive joins when retrieving objects with full data.
👤HankMoody

Leave a comment