[英]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 將其顯示為填充有預先存在的標簽的下拉列表:
如何從我的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”而不是標簽值,如下所示:
模型.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.