簡體   English   中英

使用 postman 發布請求 Manytomany 字段 DRF

[英]Post request Manytomany field DRF with postman

目標:使用“POST”從 Postman 在數據庫中創建一個新條目。

我正在嘗試從 Postman 發送數據,並且我正在使用嵌套序列化。 我已經更改了創建方法,我在下面共享了代碼段。 另外,我嘗試了這個解決方案,但沒有奏效。 有人可以指出我犯的錯誤嗎?

當我嘗試作為表單數據發布時,錯誤是{"magazine":["This field is required."]} 當我嘗試將其作為原始數據發布時,錯誤Direct assignment to the forward side of a many-to-many set is prohibited. Use magazine.set() instead. Direct assignment to the forward side of a many-to-many set is prohibited. Use magazine.set() instead.

這是我的模型:

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.ForeignKey('authors.Author', on_delete=models.CASCADE)
    magazine = models.ManyToManyField('articles.Magazine')

    def __str__(self):
        return self.title


class Magazine(models.Model):
    name = models.CharField(max_length=30)
    title = models.CharField(max_length=100)

    def __str__(self):
        return self.name

這是我的序列化程序:

class MagazineSerializer(serializers.ModelSerializer):
    class Meta:
        model = Magazine
        fields = '__all__'

class ArticleSerializer(serializers.ModelSerializer):
    author = AuthorSerializer(read_only=True, many=False)
    magazine = MagazineSerializer(many=True)
    class Meta:
        model = Article
        fields = [
            'title',
            'content',
            'author',
            'magazine',
        ]

    def create(self, validated_data):
        allmags = []
        magazine = validated_data.pop('magazine')
        for i in magazine:
            if Magazine.objects.get(id=magazine["id"]).exists():
                mags = Magazine.objects.get(id=magazine["id"])
                allmags.append(mags)
            else:
                return Response({"Error":  "No such magazine exists"}, status=status.HTTP_400_BAD_REQUEST)
            
        validated_data['author'] = self.context['request'].user
        validated_data['magazine'] = allmags
        return Article.objects.create(**validated_data)

這是我的看法:

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

class MagazineViewSet(viewsets.ModelViewSet):
    queryset = Magazine.objects.all()
    serializer_class = MagazineSerializer

    serializer_action_class = {
        'get_articles': MagazineSerializer,
    }

    @action(detail=True, url_path='articles', url_name='articles')
    def get_articles(self, request, pk=None):
        articles = Article.objects.filter(magazine=self.kwargs.get('pk'))
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data, status=200)

這就是我嘗試將數據作為原始數據發送的方式:

{
    "title": "New Post form Postman",
    "content": "Postman content new",
    "magazine": [
        {
            "id": 1,
            "name": "The Times",
            "title": "All News"
        }
    ]
}

這就是我發布為表單數據的方式:

首先,您能否澄清一下您是否還希望從嵌套序列化程序創建新的Magazine對象,或者您是否希望用戶只能為現有雜志創建Article (這似乎是第二個,因為您正在調用.exists() ) ?

第一種情況:

如果您要進行第一種情況,您還希望在同一個POST請求中創建新雜志,我建議使用drf-writeable-nested package。

第二種情況:

為此,您也應該使用drf-writeable-nested package。 或者,您可以改用此hack

from rest_framework.exceptions import ValidationError
from rest_framework import serializers
from .models import Article, Magazine

class ArticleSerializer(serializers.ModelSerializer):
    author = AuthorSerializer(read_only=True, many=False)
    magazines = MagazineSerializer(many=True, read_only=True)
    # accept list of PKs
    magazines_ids = serializers.PrimaryKeyRelatedField(
        many=True, write_only=True, queryset=Magazine.objects.all()
    )
    class Meta:
        model = Article
        fields = [
            'title',
            'content',
            'author',
            'magazines',
            'magazines_ids',
        ]

    def create(self, validated_data):
        magazines = validated_data.pop("magazines_ids", None)
        validated_data["author"] = self.context["request"].user
        article = Article.objects.create(**validated_data)
        if magazines:
            article.magazine.set(magazines)

        return article 


現在您的POST請求JSON正文應如下所示:

{
    "title": "New Post form Postman",
    "content": "Postman content new",
    "magazines_ids": [1]
}

magazines參數獲取主鍵列表的位置。


獎金

另外,出於我的好奇,您確定要使用ManytoManyField嗎? 我會假設一篇Article只能屬於您應該使用ForeignKey單個Magazine ,例如:

magazine = models.ForeignKey("articles.Magazine", related_name="articles")

然后在您的“動作”中,您可以進行以下更改:

@action(detail=True, url_path='articles', url_name='articles')
def get_articles(self, request, pk=None):
    articles = self.get_object().articles
    serializer = ArticleSerializer(articles, many=True)
    return Response(serializer.data, status=200)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM