Django REST сериализатор с несколькими внешними ключами - PullRequest
0 голосов
/ 07 апреля 2020

Привет всем и доброе утро.

Мое приложение является своего рода «менеджером хранилища», способным просматривать, искать и создавать наборы данных файлов.

У меня есть models.py как следующее:

class Author(models.Model):
    name = models.CharField(max_length=50)
    surname = models.CharField(max_length=50)
    email = models.EmailField()
    phone = models.CharField(max_length=20, blank=True)  # optional

    def __str__(self):
        return self.name


class Dataset(models.Model):
    name = models.CharField(max_length=150)  # dataset title
    description = models.TextField(blank=True)  # dataset description --> optional
    slug = models.SlugField(max_length=200, unique=True)

    author = models.ForeignKey(Author, on_delete=models.CASCADE) 

    remote = models.URLField(max_length=300)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(str(self.author.pk) + "-" + str(self.name))
        super(Dataset, self).save(*args, **kwargs)


class File(models.Model):
    creator = models.ForeignKey(Author, related_name='author', on_delete=models.CASCADE)  # the original creator of the file
    dataset = models.ForeignKey(Dataset, related_name='dataset', on_delete=models.CASCADE)  # dataset to which belongs

    name = models.CharField(max_length=100)  # file name with path
    description = models.CharField(max_length=300, blank=True)  # file description --> optional
    url = models.URLField(max_length=300)  # hot link to file

    def __str__(self):
        return self.name

Итак, я работаю с вложенными сериализаторами. Создание объекта Dataset работает следующим образом:

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ('name', 'surname', 'email', 'phone')


class FileSerializer(serializers.ModelSerializer):
    creator = AuthorSerializer(required=False)

    class Meta:
        model = File
        fields = ('name', 'description', 'url', 'creator')


class DatasetSerializer(serializers.ModelSerializer):

    author = AuthorSerializer()
    files = FileSerializer(required=False, many=True)

    class Meta:
        model = Dataset
        fields = ['name', 'description', 'remote', 'author', 'files']

    @transaction.atomic()
    def create(self, validated_data):

        author_data = validated_data.pop('author')
        dataset_author, created = Author.objects.get_or_create(**author_data)

        files_list = validated_data.pop('files')

        dataset = Dataset.objects.create(author=dataset_author, **validated_data)

        for file in files_list:
            if 'creator' in file:
                file_creator_data = file.pop('creator')
                file_creator, created = Author.objects.get_or_create(**file_creator_data)
            else:
                # file creator not specified == dataset owner
                file_creator = dataset.author
            file = File.objects.create(creator=file_creator, dataset=dataset, **file)

        return dataset

Но сейчас я не могу получить эту вложенную структуру, используя DatasetSerializer, получая эту ошибку:

Object of type 'ListSerializer' is not JSON serializable

Используя этот ListView, я могу получить только информацию об авторе и наборе данных.

class ListDataset(ListAPIView):
    queryset = Dataset.objects.all()
    serializer_class = DatasetSerializer
    lookup_field = 'author'

Но ничего о файлах, принадлежащих к набору данных.

...