Yankz Kuyateh
Yankz Kuyateh

Reputation: 743

Insert into Django JsonField without pulling the content into memory

Have a Django model

    class Employee(models.Model):
        data = models.JSONField(default=dict, blank=True)

This JSONField contains two year of data, like a ton of data.

    class DataQUery:

        def __init__(self, **kwargs):
            super(DataQUery, self).__init__()
            self.data = kwargs['data'] #is pulling the data in memory, 
           #that's what I want to avoid

            # Then We have dictionary call today to hold daily data
            today = dict()
            # ... putting stuff in today

            # Then insert it into data with today's date as key for that day
            self.data[f"{datetime.now().date()}"] = today

            # Then update the database
            Employee.objects.filter(id=1).update(data=self.data)

I want to insert into data column without pulling it into memory.

Yes, I could change default=dict to default=list and directly do

            Employee.objects.filter(id=1).update(data=today)

BUT I need today's DATE to identify the different days.

So if I don't need to pull the data column, I don't need kwargs dict. Let's say I don't init anything (so not pulling anything into memory), how can I update data column with a dictionary that's identified by today's date, such that after the update, the data column (JSONField) will look like {2021-08-10:{...}, 2021-08-11:{..}}

Upvotes: 1

Views: 1808

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476803

For relational databases, one can store multiple items that belong to the same entity by creating a new model with a ForeignKey to that other model. This thus means that we implement this as:

class Employee(models.Model):
    # …
    pass

class EmployeePresence(models.Model):
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True)
    data = models.JSONField(default=dict, blank=True)

    class Meta:
        ordering = ['employee', 'date']

In that case we thus want to add a new EmployeePresence object that relates to an Employee object e, we thus create a new one with:

EmployeePresence.objects.create(
    date='2021-08-11',
    data={'some': 'data', 'other': 'data'}
)

We can access all EmployeePresences of a given Employee object e with:

e.employeepresence_set.all()

creating, updating, removing a single EmployeePresence record is thus simpler, and can be done efficiently through querying.

Upvotes: 1

Related Questions