Django Restframework POST объект с массивом объектов в таблицы "один-ко-многим

Я новичок в django и пытаюсь найти решение, как разместить объект с массивом объектов в моей базе данных.

Вот мой пример модели.

class Fruit(models.Model):
    name = models.CharField(max_length=100)


class FruitReviews(models.Model):
    reviews = models.CharField(max_length=100)
    fruit = models.ForeignKey(Fruit, on_delete=models.CASCADE)

Вот мой сериализатор.

class FruitSerializer(serializers.ModelSerializer):
    class Meta:
        model = Fruit
        fields = '__all__'

class FruitReviewSerializer(serializers.ModelSerializer):
    class Meta:
        model = FruitReview
        fields = '__all__'

А вот мой набор представлений, который я пробую, но, к сожалению, он не работает.

@api_view('POST'])
def createFruit(request):
    serializer = FruitSerializer(data=request.data)
    serializer2 = FruitReviewSerializer(data=request.data.fruitReviews, many = True)
    if serializer.is_valid() and serializer2.is_valid():
        serializer.save()
        serializer2.save()
        return Response(status=status.HTTP_200_OK)

В принципе, например, со стороны клиента я хочу разместить что-то вроде этого

{
    "name": "Apple",
    "fruitReviews": [{
        "reviews": "Very yummy"
    }, 
    {
        "reviews": "Healthy"
    },
    {
        "reviews": "Fresh"
    }]
}

Я хочу, чтобы он был размещен в таблице fruit и fruit reviews должным образом с их отношениями один-ко-многим. Помогите пожалуйста?

Сначала вам нужно изменить ваш сериализатор для FruitReviewSerializer как:

  class FruitReviewSerializer(serializers.ModelSerializer):
      class Meta:
          model = FruitReviews
          fields = ['reviews']

Тогда в views.py:

  @api_view(['POST'])
  def createFruit(request):
      serializer = FruitSerializer(data=request.data)
      serializer2 = FruitReviewSerializer(data=request.data['fruitReviews'], many = True)
      if serializer.is_valid() and serializer2.is_valid():
          fruit = Fruit.objects.filter(name = request.data['name']).exists()
          if not fruit:
              serializer.save()
          fruit = Fruit.objects.get(name = request.data['name'])
          for i in request.data['fruitReviews']:
              review = FruitReviews(
                  fruit = fruit,
                  reviews = i['reviews']
              )
              review.save()
          return Response(status=status.HTTP_200_OK)
      else:
          return Response(status=400)

Надеюсь, это сработает!

По умолчанию вложенные сериализаторы доступны только для чтения. Если вы хотите поддерживать операции записи во вложенное поле сериализатора, вам нужно будет создать методы create() и/или update(), чтобы явно указать, как должны сохраняться дочерние отношения:

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

    def create(self, validated_data):
        tracks_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        for track_data in tracks_data:
            Track.objects.create(album=album, **track_data)
        return album

и данные должны быть такими:

data = {
    'album_name': 'The Grey Album',
    'artist': 'Danger Mouse',
    'tracks': [
        {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
        {'order': 2, 'title': 'What More Can I Say', 'duration': 264},
        {'order': 3, 'title': 'Encore', 'duration': 159},
    ],
}

ссылка: https://www.django-rest-framework.org/api-guide/relations/

Надеюсь, это будет работать без изменения ваших сериализаторов.

@api_view(['POST'])
@transaction.atomic
def create_fruit(request):
    fruit_reviews_data = request.data['fruitReviews']
    if 'fruitReviews' in request.data.keys():
        request.data.pop('fruitReviews')

    fruit_serializer = FruitSerializer(data=request.data)

    fruit_obj = None
    if fruit_serializer.is_valid(raise_exception=True):
        fruit_obj = Fruit.objects.create(**request.data)

    for fruit_review_data in fruit_reviews_data:
        fruit_review_data['fruit_id'] = fruit_obj.id
        fruit_review_serializer =FruitReviewSerializer(data=fruit_review_data)
        if fruit_review_serializer.is_valid(raise_exception=True):
            fruit_review_serializer.save()
         
    return Response(status=status.HTTP_200_OK)
Вернуться на верх