Reputation: 980
I have my Comment model
:
class Comment(models.Model):
"""A comment is a content shared by a user in some post."""
user = models.ForeignKey('users.User', on_delete=models.CASCADE, null=False)
post = models.ForeignKey('posts.Post', on_delete=models.CASCADE, null=False)
content = models.TextField(max_length=1000, null=False, blank=False)
def __str__(self):
"""Return the comment str."""
return "'{}'".format(self.content)
Its serializer:
class CommentSerializer(serializers.ModelSerializer):
"""Comment model serializer."""
user = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Comment
fields = '__all__'
def create(self, validated_data):
"""Create a new comment in some post, by request.user."""
validated_data['user'] = self.context['request'].user
return super().create(validated_data)
def list(self, request):
"""List all the comments from some post."""
if 'post' not in request.query_params:
raise ValidationError('Post id must be provided.')
q = self.queryset.filter(post=request.query_params['post'])
serializer = CommentSerializer(q, many=True)
return Response(serializer.data)
The viewset:
class CommentViewSet(viewsets.ModelViewSet):
serializer_class = CommentSerializer
queryset = Comment.objects.all()
def get_permissions(self):
permissions = []
if self.action == 'create' or self.action == 'destroy':
permissions.append(IsAuthenticated)
return [p() for p in permissions]
def get_object(self):
"""Return comment by primary key."""
return get_object_or_404(Comment, id=self.kwargs['pk']) # this is the drf's get_object_or_404 function
def destroy(self, request, *args, **kwargs):
"""Delete a comment created by request.user from a post."""
pdb.set_trace()
instance = self.get_object()
if instance.user != request.user:
raise ValidationError('Comment does not belong to the authenticated user.')
self.perform_destroy(instance)
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
So far so good when it comes to list, create and retrieve. But when it comes to delete/destroy (Idk the difference) I don't know how to get the URL for the DELETE request
.
I'm using Postman to do so.
Urls.py:
router = routers.SimpleRouter()
router.register(r'comments', CommentViewSet, basename='comments')
pdb.set_trace() # Put a pdb here to see what does router.urls have.
urlpatterns = [
# Non api/simple django views
path('create_comment/', create_comment, name='create_comment'),
path('delete_comment/', delete_comment, name='delete_comment'),
# rest api views
path('rest/', include(router.urls))
]
When I debug the router.urls
, the terminal shows this:
[<URLPattern '^comments/$' [name='comments-list']>, <URLPattern '^comments/(?P<pk>[^/.]+)/$' [name='comments-detail']>]
Why there is no url
for create
and destroy
?
I could create some Comments from the api, and I didn't even know how did I get the POST request url
for the create
function, I just guessed lol, but that's not what you want when you're programming right?
I have checked the Routers documentation but I don't get it. Please give some help! Many thanks.
Upvotes: 0
Views: 403
Reputation: 88499
The answer is simple, Django uses the comments-list
list for create and list operation and comments-detail
for update and delete operations.
That is, there are only two URL end-points, but it supports several actions, which can be performed by changing the HTTP methods
You can use HTTP GET foo-bar/comments/
to retrieve all comments where as HTTP POST foo-bar/comments/
can be used to create a new comment.
Upvotes: 1