Прямое присвоение обратной стороне вопроса с несколькими вложенными сериализаторами - PullRequest
1 голос
/ 06 марта 2020

У меня есть эта проблема, когда я выполняю тест на моем django проекте:

TypeError: Direct assignment to the reverse side of a related set is prohibited. Use files.set() instead.

Вот что я пытаюсь опубликовать

{
        "daily_hash": "w54c6w546w5v46w5v4",
        "modules": [
            {
                "module": "main",
                "commits": [
                    {
                        "commit_hash": "11feb543f016114c700046d42b912910321230da",
                        "author": "Test name 1",
                        "subject": "[TICKET] Subject of the issue",
                        "files": []
                    },
                    {
                        "commit_hash": "093b19f710c6d2358b0812434dfcf1549c9c6fbb",
                        "author": "Test name 1",
                        "subject": "[TICKET] Subject of the issue",
                        "files": []
                    }
                ]
            },
            {
                "module": "submodule",
                "commits": [
                    {
                        "commit_hash": "dce22dea52a6a4b7160034d3f84a7af7b389ee96",
                        "author": "Test name 3",
                        "subject": "[TICKET] Subject of the issue",
                        "files": [
                            {
                                "name": "my_file_1.c"
                            },
                            {
                                "name": "my_file_2.c"
                            }
                        ]
                    },
                    {
                        "commit_hash": "cee433fc4ab46464afb96d6ecae2839409fe0313",
                        "author": "Test name 4",
                        "subject": "[TICKET] Subject of the issue",
                        "files": []
                    },
                    {
                        "commit_hash": "4534f511b2a6a8c1632a1ab97b598d8e4dedada7",
                        "author": "Test name 1",
                        "subject": "[TICKET] Subject of the issue",
                        "files": []
                    }
                ]
            }
        ]
    }

Ниже вы можете найти мои модели. py:

from django.db import models
from status.models import Daily


class Component(models.Model):
    """
    Component model
    """
    module = models.CharField(max_length=40)
    daily = models.ForeignKey(Daily, on_delete=models.CASCADE)

    class Meta:
        db_table = 'gds_component'


class Commit(models.Model):
    """
    Commits model
    """
    commit_hash = models.CharField(max_length=40)
    author = models.CharField(max_length=60)
    subject = models.CharField(max_length=250)
    component = models.ForeignKey(
        Component, related_name='commits',
        on_delete=models.CASCADE)

    class Meta:
        db_table = 'gds_commit'


class File(models.Model):
    """
    Commit files model
    """
    name = models.CharField(max_length=250)
    commit = models.ForeignKey(
        Commit, related_name='files',
        on_delete=models.CASCADE)

    class Meta:
        db_table = 'gds_commit_file'

Мой сериализатор здесь:

class FileSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.File
        exclude = ['commit']


class CommitSerializer(serializers.ModelSerializer):

    files = FileSerializer(
        required=False,
        allow_null=True,
        many=True
    )

    class Meta:
        model = models.Commit
        fields = ('commit_hash', 'author', 'subject', 'files')

    def create(self, validated_data):
        files_valid_data = validated_data.pop('files')
        commit = models.Commit.objects.create(**validated_data)
        for file_data in files_valid_data:
            models.File.objects.create(commit=commit, **file_data)
        return commit


class CompoSerializer(serializers.ModelSerializer):

    commits = CommitSerializer(
        required=False,
        allow_null=True,
        many=True
    )

    class Meta:
        model = models.Component
        fields = ('module', 'daily', 'commits')

    def create(self, validated_data):
        commits_valid_data = validated_data.pop('commits')
        component = models.Component.objects.create(**validated_data)
        for commit_data in commits_valid_data:
            models.Commit.objects.create(component=component, **commit_data)
        return component

И, наконец, мой view.py

@api_view(['POST'])
def post_commit(request):

    if request.method == 'POST':
        # Get the md5 hash to get it's id
        valid_data = request.data
        hash_data = valid_data.pop('daily_hash')
        try:
            daily_obj = Daily.objects.get(daily_key=hash_data)
        except Daily.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Add daily_id to all modules
        serializer_data = valid_data.pop('modules')
        for elem in serializer_data:
            elem['daily'] = daily_obj.id

        # Serialize the data
        serializer = serializers.CompoSerializer(data=serializer_data, many=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)

        # throw an error if something wrong hapen
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Я пробовал так много вещей, и теперь я полностью потерял. Я думаю, что проблема в том, что у меня есть несколько вложенных сериализаторов, но я не уверен. Кто-нибудь может сказать мне правильное направление?

С уважением, Стеф

...