I have a simple DRF REST API that I want to use to create blog articles. I want to be able to add tags to those blog articles so users can search tags and see related articles. However, the tags may not exist yet. I have created an Article
Model with a ForeignKey field to a Tag
Model like this:
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')
Ideally what I want is to be able to POST a new Article
with a set of tags, and if any of the tags don't exist, create them in the DB. However, as it is currently, the tags need to already exist to be added to the Article
. Visually, DRF shows this as a dropdown that is populated with pre-existing tags:
How can I add or create multiple Tag
s from my Article
API endpoint?
EDIT: As requested, I've added my views.py
views.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
For completeness, here are my serializers from my REST API's serializers.py.
serializers.py:
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
urls.py:
from rest_framework import routers
router = routers.DefaultRouter()
router.register('articles', views.ArticleView)
router.register('tags', views.TagView)
urlpatterns = [
path('', include(router.urls)),
]
Overriding the create()
method of the serializer as
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With