aalberti333
aalberti333

Reputation: 1229

Default list of dicts using JSONField in Django

Django 2.0, Django-Rest-Framework 3.8, Python 3.6

I'm using a Postgres database and am trying to set up the following as a default value for the JSONField:

from django.db import models
from django.contrib.postgres.fields import JSONField

class TrainerProfile(models.Model):
    """data required to pull up trainer profile"""

    specific_workouts = JSONField(default=[{"specific": "standard session", "price": 100.00, "units": 1, "hours_per_unit": 1}, {"specific": "standard session", "price": 250.00, "units": 3, "hours_per_unit": 1}, {"specific": "standard session", "price": 300.00, "units": 5, "hours_per_unit": 1}])

    def __str__(self):
        return str(self.specific_workouts)

From the Django docs, it reads:

If you give the field a default, ensure it’s a callable such as dict (for an empty default) or a callable that returns a dict (such as a function). Incorrectly using default={} creates a mutable default that is shared between all instances of JSONField.

I want to provide a list containing dicts as the default. I'm allowed to post a list of dicts through raw data or the browsable api in Django Rest Framework, but I need to know how to set this up by default. I want it to post this as the default:

"specific_workouts": [
            {
                "price": 100.0,
                "units": 1,
                "specific": "standard session",
                "hours_per_unit": 1
            },
            {
                "price": 250.0,
                "units": 3,
                "specific": "standard session",
                "hours_per_unit": 1
            },
            {
                "price": 300.0,
                "units": 5,
                "specific": "standard session",
                "hours_per_unit": 1
            }
        ]

I'm guessing I have to override save() to do this, but I'm not sure how to actually implement that. Any help is greatly appreciated.


Update

I've tried implementing the following and am still being returned a null value as the default.

from django.db import models
from django.contrib.postgres.fields import JSONField

def default_specific_workouts():
    return [
        {
            "price": 100.0,
            "units": 1,
            "specific": "standard session",
            "hours_per_unit": 1
        },
        {
            "price": 250.0,
            "units": 3,
            "specific": "standard session",
            "hours_per_unit": 1
        },
        {
            "price": 300.0,
            "units": 5,
            "specific": "standard session",
            "hours_per_unit": 1
        }
    ]

class TrainerProfile(models.Model):
    """data required to pull up trainer profile"""

    specific_workouts = JSONField(default=default_specific_workouts)

    def __str__(self):
        return str(self.specific_workouts)

Also worth mentioning I am still returned null even if I put:

specific_workouts = JSONField(default=list)

or

specific_workouts = JSONField(default=dict)

Really not sure how to proceed from here.

Upvotes: 9

Views: 8632

Answers (1)

MrName
MrName

Reputation: 2529

As described in the excerpt you quoted, you can use any callable as the default. As such, you could create your own method to call to create the default.

def default_specific_workouts():
    # You probably want this in a variable, just copy/pasting your sample data
    # to keep the example simple
    return [
        {
            "price": 100.0,
            "units": 1,
            "specific": "standard session",
            "hours_per_unit": 1
        },
        {
            "price": 250.0,
            "units": 3,
            "specific": "standard session",
            "hours_per_unit": 1
        },
        {
            "price": 300.0,
            "units": 5,
            "specific": "standard session",
            "hours_per_unit": 1
        }
    ]

Now you can do this:

specific_workouts = JSONField(default=default_specific_workouts)

Upvotes: 5

Related Questions