Search code examples
pythondjangoserializationmany-to-many

Many-to-many relationship as JSON


Suppose I have have a model consisting of facilities that have employees which work on certain days of the week.

#models.py
class Weekday(models.Model):
    name = models.CharField()   # 'Monday', 'Tuesday', etc.

class Facility(models.Model):
    name = models.CharField()

class Employee(models.Model):
    name = models.CharField()
    facility = models.ForeignKey(Facility)
    # e.g. works on Mondays and Tuesdays
    weekdays = models.ManyToManyField(Weekday)

Now I want my TemplateView to generate a JSON that lists the employees of a given facility by the days of the week. This needs to be JSON because a weekly calendar shall be rendered by javascript.

# views.py
class CareFacility(DetailView):
    model = Facility

    def get_context_data(self):
        return {
            'week_plan_json': ?
        }

The JSON may be something like:

[
    {
        'model': 'Weekday',
        'name': 'Monday',
        'employees': [
            {
                'model': 'Employee',
                'name': 'John'
            },
            {
                'model': 'Employee',
                'name': 'Ida'
            }
        ]
    },
    {
        'model': 'Weekday',
        'name': 'Tuesday',
        'employees': [
            {
                'model': 'Employee',
                'name': 'John'
            }
        ]
    },
    {
        # Wednesday
        # etc...
    }
]

The exact format may be different, but I am wondering how to combine the three models in a way that they are grouped by Weekday


Solution

  • Use the related objects references Django provides. The following code snippet should show you the idea and point you in the right direction so that you can adapt it to your needs:

    from collections import defaultdict
    d = defaultdict(list)
    f = Facility()  # Assuming this is the facility you're looking at
    for employee in f.employee_set.all():
        for weekday in employee.weekdays.all():
            d[weekday.name].append(employee.name)
    return dict(d)
    

    This should give you something like:

    {
        'Monday': ['John', 'Ida'],
        'Tuesday': ['John'],
        ...
    }
    

    For more info on relations check the Django documentation.