Reputation: 134
I am currently building a Django React app and I want the users to be able to create an instance of a model (listing) from the frontend. I was trying to build the backend, but when I try the url: http://localhost:8000/api/listings/create on Postman I get an error : "detail":"Method "POST" not allowed."
Also, if I use "/listings/admin/create" instead, I do not get this error.
My model :
class Listing(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.DO_NOTHING)
slug = models.CharField(max_length=200, unique=True)
title = models.CharField(max_length=150)
photo_main = models.ImageField(upload_to='photos/%Y/%m/%d/', default='photos/default.jpg')
description = models.TextField(blank=True)
def __str__(self):
return self.title
My view :
class CreateListingView(APIView):
parser_classes = [MultiPartParser, FormParser]
queryset = Listing.objects.all()
serializer_class = ListingSerializer
def post(self, request, format=None):
print(request.data)
serializer = ListingSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
else:
return Response(serializer.data,status=status.HTTP_400_BAD_REQUEST)
My app Urls :
from django.urls import path
from .views import ListingsView, ListingView, SearchView,CreateListingView
app_name = 'listings'
urlpatterns = [
path('', ListingsView.as_view(),name='listings'),
path('search', SearchView.as_view(),name='listingssearc'),
path('<slug>', ListingView.as_view(),name='listingsdetails'),
path('create', CreateListingView.as_view(),name='listingscreate')
]
My project urls :
urlpatterns = [
path('api-auth/', include('rest_framework.urls')),
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/accounts/', include('accounts.urls')),
path('api/artists/', include('artists.urls')),
path('api/listings/', include('listings.urls', namespace='listings')),
path('api/contact/', include('contact.urls')),
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += [re_path(r'^.*', TemplateView.as_view(template_name='index.html'))]
So what did I do wrong? I don't understand why I get a 405 error.
Thanks for reading!
Upvotes: 0
Views: 360
Reputation: 3717
The url-pattern is tried one line after the other.
in your urlpatterns you catch the call to "create" in the line before as slug:
urlpatterns = [
path('', ListingsView.as_view(),name='listings'),
path('search', SearchView.as_view(),name='listingssearc'),
path('<slug>', ListingView.as_view(),name='listingsdetails'),
path('create', CreateListingView.as_view(),name='listingscreate')
]
so it is going to listingsdetails which obviously does not allow post requests.
change it to:
urlpatterns = [
path('', ListingsView.as_view(),name='listings'),
path('search', SearchView.as_view(),name='listingssearc'),
path('create', CreateListingView.as_view(),name='listingscreate'),
path('<slug>', ListingView.as_view(),name='listingsdetails')
]
then it is only catched by the last line if it has a slug that is not search or create.
Upvotes: 2
Reputation: 142
You can try changing
class CreateListingView(APIView):
to
class CreateListingView(generics.ListCreateAPIView)
Upvotes: 0
Reputation: 422
It should be like this:
class CreateListingView(APIView):
def post(self, request, format=None):
print(request.data)
serializer = ListingSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
else:
return Response(serializer.data,status=status.HTTP_400_BAD_REQUEST)
For reference please see this drf APIView
Upvotes: 0