Rob Oakes
Feb 01, 2022

Migrating to the Django 3.1 JSONField

One of the cool features introduced in Django 3.1 was the JSONField. It allows you to store semi-structured data alongside other information in the database. Adopting new things can be scary for an existing project, though, because you have to migrate to it. In this blog post, we take a look at migrating to JSONField in an existing project and how that works.

One of the cool features that was introduced in Django 3.1 was the JSONField. JSONField allows for you to store semi-structured data alongside other data fields in PostgreSQL, MySQL, and SQLite databases and supports introspection, lookups, and transforms. The example in the listing below shows how the JSONField can be added to a model, populated with key/value pairs, and queried.

from django.db import models

class Patient(models.Model):
    name = models.CharField(max_length=256)
    data = models.JSONField()


# Create a patient instance
Patient(name='John Doe', data={
    'address': '123 Some House Number', 
    'city': 'Some City',
    'state': 'Utah',
})

# Filter and delete the patient
Patient.objects.filter(patient='John Doe', data__state='Utah')

Even though there has been a PostgreSQL specific field which provided similar functionality, it was only limited to a single database backend and not something I've used much. I'm not always guaranteed that solutions will be deployed to PostgreSQL. The potential to mix structured and semi-structured data is really powerful, however, and there are a number of third-party fields implemented which take JSON data and store it as a string in the database. While this doesn't give you a query API, it does allow you to store metadata without a schema (which can be useful). The forms builder inside of Acorn uses such a field to store individual form submissions.

I recently needed to expose form submissions in Acorn via REST and I thought that it would be nice if the API had the ability to query and filter the submissions. Implementing logic to provide that type of an interface on top of a CharField or TextField would be difficult; so I figured I would upgrade the form_data to a JSONField and see how the process went.

Here's what my model looked like before JSONField:

from django.db.models import TextField, Model

class FormSubmission(Model):
    ...
    form_data = TextField()

And here is what it looked like after:

from django.db.models import TextField, JSONField, Model

class FormSubmission(Model):
    ...
    form_data = JSONField()

The upgrade was extremely smooth! Well done Django Development team!

To migrate a test site, all I had to do create and apply the migrations (manage.py makemigrations and manage.py migrate), and swap out a few json.dumps and json.loads calls. The built-in Django migrations code otherwise handled the data conversion under the hood.

Django 3.1: JSONField Migrations Screenshot
Migrating to a JSONField in Django 3.1 is painless. If moving from a TextField or CharField with a serialized string, the data will be converted for you as part of the migration process.

I haven't had a chance to play with new query capabilities yet, but JSONField is a very cool piece of kit and worth checking out.

Rob Oakes Feb 01, 2022
More Articles by Rob Oakes

Loading

Unable to find related content

Comments

Loading
Unable to retrieve data due to an error
Retry
No results found
Back to All Comments