Search code examples
pythonjsondjangopostput

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


I am a novice at Django and already GET data . Part of some json as follows:

{
    "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": []
    }
},

This is my 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")

I try to override create() and update() method to POST json in serializer.py, but it's too many layer to link. I have no idea about this.

Below is my create method, but it only can POST MemberAccount and 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

The POST json message:

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

Solution

  • Just save related models accordingly like this:

    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