How To Store List Type Field In Django? (3 Different Solutions)

Standard

Hi everyone,

The topic of my article today is very specific. However, with this question, I wanted to write an article on this subject, as I had the opportunity to see how more than one approach to a problem can be taken…

Description of the Problem

Let’s say you have a web project and one of your fields in the database needs to be listed. However, you need an alternative solution as you cannot keep the list directly in the database by default. How can you solve it?

Solution 1: Converting your List in Model and Storing it as JSON

If the database you are using supports the JSON data type, this solution is easy to implement. Let’s say you are building a database of a car trading company and you decide to keep a list of models under each brand;

from django.db import models
import json


class Brand(models.Model):
    brand_name = models.CharField(max_length=200)
    _car_models = models.CharField(db_column="car_models", max_length=500)

    @property
    def car_models(self):
        return json.loads(self._car_models)

    @car_models.setter
    def car_models(self, x):
        self._car_models = json.dumps(x)

Let’s test it;

    # Save
    # sample_brand = Brand()
    # sample_brand.brand_name = "Mercedes"
    # sample_brand.car_models = ["c200", "c180", "e220d"]
    # sample_brand.save()

    # Get
    # sample_brand = Brand()
    # print(Brand.objects.get().car_models)
    # expected output: ['c200', 'c180', 'e220d']

Solution 2: Setting Up ManytoMany Relationship

It may be more logical to keep your columns, which should be kept in a list in the solution, by creating a different table, which can even be considered more optimized (thus, DB allows you to write complex queries);

class TruckModel(models.Model):
    truck_name = models.CharField(max_length=100)

    def __str__(self):
        return self.truck_name


class TruckBrand(models.Model):
    brand_name = models.CharField(max_length=100)
    truck_models = models.ManyToManyField(TruckModel)

    def __str__(self):
        return self.brand_name

Let’s test this method;

 # Creation
ford = TruckBrand(brand_name="Ford")
ford.save()
truck_model_1 = TruckModel(truck_name="F150")
truck_model_1.save()
truck_model_2 = TruckModel(truck_name="F250")
truck_model_2.save()
truck_model_3 = TruckModel(truck_name="F350")
truck_model_3.save()

# Relation
ford.truck_models.add(truck_model_1)
ford.truck_models.add(truck_model_2)
ford.truck_models.add(truck_model_3)
ford.save()

# Get
print(ford.truck_models.last().truck_name)
# Expected output: 'F350'

Solution 3: Using JSONField (Database Dependent)

Although I wouldn’t recommend it, since a project’s database will not change easily, I wanted to write it as an alternative, if you are using PostgreSQL;

from django.db.models import JSONField

In this way, it is possible to directly keep it in the form of a JSON object in the form of a column.

Final Opinion

There is more than one solution to the problems we encounter most of the time. As we can see in this example, each solution leads to the answer, but each has its advantages and disadvantages. For example, if we prefer the 1st solution, there is no need to add a new table, but it can give us a problem when we want to make a query in terms of performance. While the 2nd solution puts a load on the DB because it performs operations on more than one table, the 3rd solution may not work for us depending on the database type.

See you in my next post 🙂

You can find the sample codes of the project here:

https://github.com/Natgho/django-orm-listfield

Sources;
https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.JSONField
https://pganalyze.com/blog/postgres-jsonb-django-python
https://pypi.org/project/django-jsonfield-backport/
https://stackoverflow.com/questions/49955905/django-jsonfield-filtering-queryset
https://stackoverflow.com/questions/22340258/list-field-in-model

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.