Reputation: 177
I want to create a custom or modified url using router for ModelViewSet.
Current scenario:
/models.py
class BlogPost(models.Model):
title = models.CharField(max_length=300)
description = models.TextField()
slug = models.SlugField(max_length=300, unique=True)
/serializers.py
class BlogListSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
exclude = ('id',)
/views.py
class BlogViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogListSerializer
/urls.py
router = DefaultRouter()
router.register(r'blog', BlogViewSet, basename='blog')
urlpatterns = router.urls
Now, I can access the url as below:
list https://localhost:8000/blog
retrieve https://localhost:8000/blog/1
As You can see that the retrieve url can be called using the pk or id. But I have created a model field called slug and its unique. My question is that how do I modify the retrieve url so that I can call the retrieve url using the slug field. For example: https://localhost:8000/blog/test-slug
Note: Why do I want to create a url using slug? Answer: I want to use the urls for sitemap.
Upvotes: 0
Views: 1667
Reputation: 196
If your api needs to return results by querying the slug field (and not the pk
field) you could use the lookup_field
and lookup_url_kwarg
of DRF.
The pk
or id
field lookup is the default lookup and mentioned in DRF docs.
https://www.django-rest-framework.org/api-guide/generic-views/
views.py
class BlogViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogListSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'slug'
Upvotes: 4
Reputation: 3392
class Blogdetail(generics.RetrieveAPIView):
queryset = BlogPost.objects.all()
serializer_class = BlogDetailsSerializer
def get_object(self):
slug = self.kwargs["slug"]
obj = get_object_or_404(BlogPost, slug=slug)
return obj
class BlogUrlHyperlinkedIdentityField(serializers.HyperlinkedIdentityField)
def get_url(self, obj, view_name, request, format):
kwargs = {
"slug": obj.slug
}
return reverse(view_name, kwargs=kwargs, request=request, format=format)
class BlogListSerializer(serializers.ModelSerializer):
url = BlogUrlHyperlinkedIdentityField("blog_detail")
class Meta:
model = BlogPost
fields = [
"url",.....]
Add the url also
path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),
Upvotes: 0
Reputation: 2093
# add a new url in your urlpatterns
urlpatterns = [
path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),
]
# In views.py define a class Blogdetail or make changes in the existing class
class Blogdetail(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogDetailsSerializer
def get_queryset(self):
slug = self.request.query_params.get("slug", None)
if slug == None:
queryset = self.queryset
else:
queryset = self.queryset.filter(slug = slug)
return queryset
Upvotes: 0