Django REST:如何在嵌套的 ModelSerializer 中 POST 和 PUT 数据

Django REST: How to POST and PUT Data in Nested ModelSerializer

我是 Django 的新手,已经获取了数据。 部分json如下:

{
    "pk": 4,
    "account": "user4",
    "password": "5340",
    "UserDatas": {
        "memberAccount_id": 4,
        "username": "Dylan",
        "gender": true,
        "score": 100,
        "photo": "photos/2016/05/16/avatar.png",
        "TaskDatas": [
            {
                "userData_id": 4,
                "task_name": "make a phone call",
                "task_is_group": false,
                "task_time": "2015/05/18",
                "task_score": 2,
                "task_member_list": "",
                "task_bulletin": "phone number is 1234-5678"
            }
        ],
        "FriendsDatas": [],
        "ChatroomDatas": []
    }
},

这是我的 models.py

class MemberAccount(models.Model):
    account = models.CharField(max_length=50)
    password = models.CharField(max_length=30)

    def __str__(self):
        return  "%s : %s" % (self.account, self.password)

class UserData(models.Model):
    memberAccount_id = models.OneToOneField(
        MemberAccount,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name='UserDatas',
        blank=True
    )
    username = models.CharField(max_length=30, default="")
    gender = models.BooleanField()
    score = models.IntegerField()
    photo = models.ImageField(upload_to ="photos/%Y/%m/%d/", null=True ,blank=True)

    class Meta:
        unique_together = ('memberAccount_id', 'username')
        order_with_respect_to = 'memberAccount_id'

    def __str__(self):
        return "%s : %s" % (self.memberAccount_id, self.username)

class TaskData(models.Model):
    userData_id = models.ForeignKey(UserData, related_name='TaskDatas', null=True)
    task_name = models.CharField(max_length=100, default="")
    task_is_group = models.BooleanField()
    task_time= models.CharField(max_length=30)
    task_score = models.IntegerField()
    task_member_list = models.CharField(max_length=100, null=True ,blank=True)
    task_bulletin = models.TextField(blank=True, default='')

    class Meta:
        unique_together = ('userData_id', 'task_name')
        order_with_respect_to = 'userData_id'

    def __str__(self):
        return  "%s : %s" % (self.userData_id, self.task_name)

class ChatroomData(models.Model):
    userdata_cid = models.ForeignKey(UserData, related_name='ChatroomDatas', null=True, blank=True)
    chatroom_member = models.CharField(max_length=30)
    chatroom_contents = models.TextField(blank=True, default='')

    def __str__(self):
    # 在Python3中使用 def __str__(self)
    return "%s : %s" % (self.userdata_cid, self.chatroom_member)


class FriendsData(models.Model):
    usersData_id = models.ForeignKey(UserData, related_name='FriendsDatas', null=True)
    friend_name = models.CharField(max_length=30)
    friend_account = models.CharField(max_length=50)

    class Meta:
        unique_together = ('usersData_id', 'friend_name')
        order_with_respect_to = 'usersData_id'

    def __str__(self):
    # 在Python3中使用 def __str__(self)
        return  "%s : %s" % (self.usersData_id, self.friend_name)

class SubtaskData(models.Model):
    taskData_id = models.ForeignKey(TaskData, related_name='SubtaskDatas', null=True)
    subtask_name = models.CharField(max_length=100)
    subtask_deadline = models.CharField(max_length=30)
    subtask_completion= models.IntegerField()
    subtask_importance = models.IntegerField()
    subtask_item = models.TextField(blank=True, default='')


    class Meta:
        unique_together = ('taskData_id', 'subtask_name')
        order_with_respect_to = 'taskData_id'

    def  __str__(self):
    # 在Python3中使用 def __str__(self)
        return  "%s : %s" % (self.taskData_id, self.subtask_name)

views.py

@api_view(['GET','POST'])
def jobterm_list(request, format=None):

    if request.method=="GET":
        MemberAccounts =list(MemberAccount.objects.all()) 
        serializer = MemberAccountSerializer(MemberAccounts,many=True)
        return Response(serializer.data)


    elif request.method == 'POST':
        #print (request.body)
        serializer = MemberAccountSerializer(data=request.data)

        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)



@api_view(['GET', 'PUT', 'DELETE']) #
def jobterm_detial(request,pk, format=None):
    try:
        member_Account = MemberAccount.objects.get(pk=pk)
    except MemberAccount.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == "GET":
        serializer = MemberAccountSerializer(member_Account)
        return Response(serializer.data)

    elif request.method == "PUT":
        serializer = MemberAccountSerializer(member_Account,data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)

    elif request.method == "DELETE":
        member_Account.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

serializer.py

class ChatroomDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = ChatroomData
        fields = ("userdata_cid", "chatroom_member", "chatroom_contents")

class TaskDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = TaskData
        fields = ("userData_id", "task_name", "task_is_group",
              "task_time", "task_score", "task_member_list",
              "task_bulletin")

class FriendsDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = FriendsData
        fields = ("usersData_id","friend_name","friend_account")

class UserDataSerializer(serializers.ModelSerializer):
    TaskDatas = TaskDataSerializer( many = True )
    FriendsDatas = FriendsDataSerializer( many = True )
    ChatroomDatas = ChatroomDataSerializer( many = True )
    class Meta:
        model = UserData
        fields = ("memberAccount_id","username","gender","score",
              "photo","TaskDatas","FriendsDatas","ChatroomDatas")

class MemberAccountSerializer(serializers.ModelSerializer):
    UserDatas = UserDataSerializer( required = False )
    class Meta:
        model = MemberAccount
        fields = ("pk","account","password","UserDatas")

class SubtaskDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = SubtaskData
        fields = ("taskData_id","subtask_name","subtask_deadline","subtask_completion",
              "subtask_importance","subtask_item")

我尝试在 serializer.py 中将 create() 和 update() 方法重写为 POST json,但是层数太多 link。我对此一无所知。

下面是我的创建方法,但它只能POST MemberAccount 和UserData。

def create(self, validated_data):

    memberaccount = MemberAccount.objects.create(account = validated_data['account'], 
                                                password = validated_data['password'] )

    User_Datas = validated_data.pop('UserDatas')

    for item in User_Datas:
        userdata = UserData.objects.create(username = User_Datas.get('username'),
                              gender = User_Datas.get('gender'),
                               score = User_Datas.get('score'),
                               photo = User_Datas.get('photo'))

        userdata.save()
    return memberaccount

POST json 消息:

{"account":"try3","password":"8493","UserDatas":{"memberAccount_id":0,"username":"Amy","gender":false,"score":100,"photo":null,"TaskDatas":[],"FriendsDatas":[],"ChatroomDatas": []}}

这些是我看到的选项:

  • 如果您不介意原子性(我不推荐此选项),您可以创建一组链式 POST 调用
  • 拆分您的前端 UI/UX 这样您就可以隔离数据并使其易于处理。例如,每个面板都有不同的面板
  • 在编辑时保存(在前端),因此您可以像以前一样同步小块数据
  • 处理视图上的数据(后端)。您还需要处理原子性,但您可以依靠验证器。在这种情况下,您需要为它们中的每一个创建序列化程序实例
  • 使用序列化器列表作为属性创建嵌套序列化器,但正如您所说,您可能需要处理多个层

只需将相关模型相应地保存如下:

def create(self, validated_data):

    memberaccount = MemberAccount.objects.create(account = validated_data['account'],
                                            password = validated_data['password'] )
    memberaccount.save()
    User_Datas = validated_data.pop('UserDatas')

    userdata = UserData.objects.create(username = User_Datas.get('username'),
        gender = User_Datas.get('gender'),
        score = User_Datas.get('score'),
        photo = User_Datas.get('photo'),)
    userdata.memberAccount_id = memberaccount

    userdata.save()

    Task_Datas = User_Datas.get('TaskDatas')
    for task in Task_Datas:
        taskdata = TaskData(
            task_name = task.get('task_name'), 
            task_is_group = task.get('task_is_group'), 
            task_time = task.get('task_time'), 
            task_score = task.get('task_score'), 
            task_member_list = task.get('task_member_list'), 
            task_bulletin = task.get('task_bulletin'), 
        )
        taskdata.userData_id = userdata
        taskdata.save()

    return memberaccount