I have two models with many-to-many relationship and I also have nested routers between them.
When I'm trying to create a tag at the endpoint api/page/4/tags/, tag is created in the database for tags, but nothing happend in my table for many to many relationship. How can I fix it? I want to update my M2M everytime a new tag is created. Thank you
models.py
class Tag(models.Model):
title = models.CharField(max_length=30, unique=True)
class Page(models.Model):
...
tags = models.ManyToManyField(Tag, related_name='pages')
My serializers.py
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
class PageSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Page
fields = ['id', 'title', 'uuid', 'description', 'owner', 'is_private', 'tags']
views.py
class PageViewSet(viewsets.ModelViewSet):
queryset = Page.objects.all()
serializer_class = PageSerializer
def perform_update(self, serializer):
serializer.save(owner=self.request.user)
class TagViewSet(viewsets.ModelViewSet):
serializer_class = TagSerializer
queryset = Tag.objects.all()
class NestedTagViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
queryset = Tag.objects.all()
serializer_class = TagSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
def get_page(self, request, page_pk=None):
page = get_object_or_404(Page.objects.all(), pk=page_pk)
self.check_object_permissions(self.request, page)
return page
def create(self, request, *args, **kwargs):
self.get_page(request, page_pk=kwargs['page_pk'])
return super().create(request, *args, **kwargs)
def get_queryset(self):
return Tag.objects.filter(pages=self.kwargs['page_pk'])
def list(self, request, *args, **kwargs):
self.get_page(request, page_pk=kwargs['page_pk'])
return super().list(request, *args, **kwargs)
my urls.py
from django.urls import path, include
from rest_framework_nested import routers
from .views import PageViewSet, TagViewSet, NestedTagViewSet
router = routers.SimpleRouter()
router.register(r'pages', PageViewSet)
pages_router = routers.NestedSimpleRouter(router, r'pages', lookup='page')
pages_router.register(r'tags', NestedTagViewSet, basename='page-tags')
app_name = 'page'
urlpatterns = [
path(r'', include(router.urls)),
path(r'', include(pages_router.urls)),
]
I'm trying to create new tags at the api/ ^pages/(?P<page_pk>[^/.] )/tags/$ [name='page-tags-list'] host
CodePudding user response:
I will assume after you create a tag you want to add it to the current page in the route.
With this in mind, you have a tag viewset, so you need to override the create method when you are creating a tag.
class TagViewSet(viewsets.ModelViewSet):
serializer_class = TagSerializer
queryset = Tag.objects.all()
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)
new_tag = Tag.objects.get(id=response["id"])
page = Page.objects.get(id=kwards["page_pk"])
page.tags.add(new_tag)
return response
The idea is to create a tag and after you create it, append it to the page M2M relationship. Hope this helps.