I am doing a project for uni and it decided to make it in Django to learn something new. I start to regret that... and I hope that you can help.
I am creating a simple API that performed well previously, but after adding the related class into a model, it allows me only to perform GET & POST operations, and I don't know why it happens and how to fix that - I have specified http methods in viewsets. I want to perform PUT, PATCH & DELETE operations as well.
models.py:
from django.db import models
class Author(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=60,blank=True,null=True)
last_name = models.CharField(max_length=60,blank=True,null=True)
description = models.CharField(max_length=1000,blank=True,null=True)
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Quote(models.Model):
id = models.AutoField(primary_key=True)
content = models.CharField(max_length=1000)
author = models.ForeignKey(Author, on_delete=models.SET_NULL,related_name='quotes',null=True)
source = models.CharField(max_length=60,blank=True,null=True)
context = models.CharField(max_length=1000,blank=True,null=True)
year = models.IntegerField(blank=True,null=True)
def __str__(self):
return self.content
serializers.py:
from rest_framework import serializers
from .models import Quote, Author
class QuoteSerializer(serializers.ModelSerializer):
class Meta:
model = Quote
fields = ('id','content','author','source','year','context')
lookup_field = 'author'
class AuthorSerializer(serializers.HyperlinkedModelSerializer):
quotes = QuoteSerializer(many=True, read_only=True)
class Meta:
model = Author
fields = ('id','first_name','last_name','description','quotes')
urls.py:
from django.urls import include, path
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'authors', views.AuthorViewSet,basename='authors')
router.register(r'quotes', views.QuoteViewSet,basename='quotes')
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
views.py:
from rest_framework import viewsets
from rest_framework.exceptions import NotFound
from rest_framework.response import Response
from rest_framework import status
from .serializers import QuoteSerializer, AuthorSerializer
from .models import Quote, Author
class AuthorViewSet(viewsets.ModelViewSet):
http_method_names = ['get', 'put', 'post','patch', 'delete']
serializer_class = AuthorSerializer
def get_queryset(self):
queryset = Author.objects.all().order_by('id')
id = self.request.query_params.get('id')
first_name = self.request.query_params.get('first_name')
last_name = self.request.query_params.get('last_name')
if id is not None:
queryset = queryset.filter(id=id)
if first_name is not None:
queryset = queryset.filter(first_name=first_name)
if last_name is not None:
queryset = queryset.filter(last_name=last_name)
if queryset:
return queryset
else:
raise NotFound
def destroy(self, request, *args, **kwargs):
obj = self.get_object()
self.perform_destroy(obj)
return Response(data={'detail': "Deleted successfully"},status=status.HTTP_204_NO_CONTENT)
class QuoteViewSet(viewsets.ModelViewSet):
http_method_names = ['get', 'put', 'post','patch', 'delete']
serializer_class = QuoteSerializer
lookup_field = 'author'
def get_queryset(self):
queryset = Quote.objects.all().order_by('id')
id = self.request.query_params.get('id')
author = self.request.query_params.get('author')
source = self.request.query_params.get('source')
year = self.request.query_params.get('year')
if id is not None:
queryset = queryset.filter(id=id)
if author is not None:
queryset = queryset.filter(author=author)
if source is not None:
queryset = queryset.filter(source=source)
if year is not None:
queryset = queryset.filter(year=year)
if queryset:
return queryset
else:
raise NotFound
def destroy(self, request, *args, **kwargs):
obj = self.get_object()
self.perform_destroy(obj)
return Response(data={'detail': "Deleted successfully"},status=status.HTTP_204_NO_CONTENT)
CodePudding user response:
As a far i know when you use a ModelViewSet, you have 5 methods allowed, list(), retrieve(), create(), update(), destroy(), and the queryset that count as a GET that you always have to define. i can see that you want to use mixins(perform_destroy-DestroyModelMixin). that's no necesary you have everything to do without that.
- list(self, request)->GET, create(self, request)->POST.
you have specify an id for this ones:
- retrieve()->GET, destroy()->DELETE, update() -> PUT
don't need this variable 'http_method_names', when you use postman define what method want to execute.
You methods should be like this.
def destroy(self, request, pk=None, *args,**kwargs):
obj = self.model.objects.filter(id=pk)
if obj:`enter code here`
obj.delete()
return Response({'detail':'Deleted Succesfully'}, status=status.HTTP_204_NO_CONTENT)
return Response({'error':'record doesn't exists'}, status=status.HTTP_400_BAD_REQUEST)
IN POSTMAN METHOD:DELETE URL: http://localhost/autors/1/
same with retrieve that it's just to show infomation about one object. create and list doesn't need and id 'cause you know :D I hope it has been helpfull i'm learning too =)
CodePudding user response:
If somebody is curious - the problem was the lookup field in QuoteViewset that was creating a problem with my API's hyperlink. After deletion, it works fine.