Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
179 views
in Technique[技术] by (71.8m points)

python - How to serialize three models with many to many relationships in Django Rest Framework

I have three base models:

class User(models.Model):
    displayName= models.CharField(max_length=128)

class Cell(models.Model):
    title = models.CharField(max_length=128)

class List(models.Model):
    title = models.CharField(max_length=128)

And three many-to-many relationships between them:

class UserCell(models.Model):
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE
    )
    cell = models.ForeignKey(
        Cell,
        on_delete=models.CASCADE
    )
    value = models.SmallIntegerField()

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['user', 'cell'],
                name='unique_UserCell'
            )
        ]

class UserList(models.Model):
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE
    )
    target_list = models.ForeignKey(
        List,
        on_delete=models.CASCADE
    )
    last_updated = models.DateTimeField(default=timezone.now)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['user', 'target_list'],
                name='unique_UserList'
            )
        ]

class CellAssignment(models.Model):
    target_list = models.ForeignKey(
        List,
        on_delete=models.CASCADE
    )
    cell = models.ForeignKey(
        Cell,
        on_delete=models.CASCADE
    )
    idx = models.SmallIntegerField()

    class Meta:
        ordering = ['idx']
        constraints = [
            models.UniqueConstraint(
                fields=['target_list', 'idx'],
                name='unique_cellAssignment'
            )
        ]

My view is given a List.id and a User.id and I want to return data in the following format, or something similar:

{"List.id": 2, "List.title": "The Big List of Cells", "List.created_date": "2020-10-02T18:14:02Z",  "cells": [{"target_list.id": 2, "Cell.id": 6, "CellAssignment.idx": 0, "Cell.title": "The first cell", "UserCell.value": 4}, {"target_list.id": 2, "Cell.id": 12, "CellAssignment.idx": 1, "Cell.title": "This is the second cell and so on", "UserCell.value": 9}, ...]}

Is it possible to do this by nesting serializers, or should I query the relationships separately and join the data in the view? Any info on the difference in performance between the two approaches would be additionally appreciated.

Edit (12/24). Current Serializers:

class UserCellSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserCell
        fields = '__all__'

class CellSerializer(serializers.ModelSerializer):
    class Meta:
        model = Cell
        fields = ['id', 'title']

class CellAssignmentSerializer(serializers.ModelSerializer):
    cell_title = serializers.ReadOnlyField(source='cell.title')
    cell_value = serializers.ReadOnlyField(source='cell.user_cell.value')

    class Meta:
        model = CellAssignment
        #target_list and cell are not strictly needed below, as of now. good for debug tho.
        fields = ['target_list', 'idx', 'alt_title', 'cell_title', 'cell_value']

class ListSerializer(serializers.ModelSerializer):
    cell_details = CellAssignmentSerializer(read_only=True, many=True)

    class Meta:
        model = List
        fields = ['id', 'title', 'created_date', 'cell_details']

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

https://www.django-rest-framework.org/api-guide/relations/#nested-relationships

You can make nested serializer.

  1. Make each serializer for model.
  2. Make all serializers nested.

First, Just make each serializer and then merge all of them for nested. It should be working.

Updated,

cell = models.ForeignKey(
        Cell,
        on_delete=models.CASCADE,
        related_name="user_cells"
    )

Then, you can access user_cell from cell like

  cell_instance.user_cells.all()

or whatever you want.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.6k users

...