簡體   English   中英

Django Rest Framework - 在 POST 上創建外鍵對象

[英]Django Rest Framework - Create foreign key object on POST

我有一個簡單的 DRF REST API,我想用它來創建博客文章。 我希望能夠為這些博客文章添加標簽,以便用戶可以搜索標簽並查看相關文章。 但是,標簽可能還不存在。 我創建了一個帶有外鍵字段的Article模型到Tag模型,如下所示:

class Tag(models.Model):

    name = models.CharField(max_length=32)

    def _str__(self):
        return self.name

    class Meta:
        ordering = ('name',)

class Article(models.Model):

    title = models.CharField(max_length=256)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    tags = models.ForeignKey(Tag, on_delete=models.CASCADE, blank=True, default=None)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ('date', 'id')

理想情況下,我想要的是能夠發布帶有一組標簽的新Article ,如果任何標簽不存在,請在數據庫中創建它們。 但是,目前,標簽需要已經存在才能添加到Article 從視覺上看,DRF 將其顯示為填充有預先存在的標簽的下拉列表:

DRF接口

如何從我的Article API 端點添加或創建多個Tag

編輯:根據要求,我添加了我的 views.py

視圖.py:

from api.blog.serializers import ArticleSerializer, TagSerializer
from rest_framework import viewsets

# /api/blog/articles
class ArticleView(viewsets.ModelViewSet):

    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

# /api/blog/tags
class TagView(viewsets.ModelViewSet):

    queryset = Tag.objects.all()
    serializer_class = TagSerializer

為了完整起見,這里是我的 REST API 的 serializers.py 中的序列化程序。

序列化程序.py:

class ArticleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Article
        fields = '__all__'


class TagSerializer(serializers.ModelSerializer):

    class Meta:
        model = Tag
        fields = '__all__'

網址.py:

from rest_framework import routers

router = routers.DefaultRouter()
router.register('articles', views.ArticleView)
router.register('tags', views.TagView)

urlpatterns = [
    path('', include(router.urls)),
]

將序列化程序的create()方法重寫為

class ArticleSerializer(serializers.ModelSerializer):
    tags = serializers.CharField()

    class Meta:
        model = Article
        fields = '__all__'

    def create(self, validated_data): tag = validated_data.pop('tags') tag_instance, created = Tag.objects.get_or_create(name=tag) article_instance = Article.objects.create(**validated_data, tags=tag_instance) return article_instance

好的,感謝@JPG 的幫助。 這就是我的結局。 它允許用戶將空格分隔的標簽添加到/api/blog/article端點上的CharField 當執行 POST 請求時,標簽在空格上拆分, get_or_create() d(為此我需要將Tag.name設為主鍵),然后使用article.tags.set(tag_list)添加到Article . 正如@JPG 和@Martins 所建議的, ManyToManyField()是最好的方法。

這是我的完整代碼:

序列化程序.py:

class ArticleSerializer(serializers.ModelSerializer):

    class TagsField(serializers.CharField):

        def to_representation(self, tags):
            tags = tags.all()
            return "".join([(tag.name + " ") for tag in tags]).rstrip(' ')


    tags = TagsField()

    class Meta:
        model = Article
        fields = '__all__'

    def create(self, validated_data):

        tags = validated_data.pop('tags') # Removes the 'tags' entry
        tag_list = []
        for tag in tags.split(' '):
            tag_instance, created = Tag.objects.get_or_create(name=tag)
            tag_list += [tag_instance]

        article = Article.objects.create(**validated_data)
        print(tag_list)
        article.tags.set(tag_list)
        article.save()
        return article


class TagSerializer(serializers.ModelSerializer):

    class Meta:
        model = Tag
        fields = '__all__'

請注意,我必須創建一個自定義TagField()並覆蓋to_representation() 這是因為如果我使用常規serializer.CharField()標簽顯示為:“Blog.tag.None”而不是標簽值,如下所示:

Blog.tag.None

模型.py:

class Tag(models.Model):

    name = models.CharField(max_length=32, primary_key=True)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('name',)

class Article(models.Model):

    title = models.CharField(max_length=256)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    tags = models.ManyToManyField(Tag)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ('date', 'id')

暫無
暫無

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

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