“detail”: “Method \”GET\“ not allowed.” Django Rest Framework - python

I know this question was duplicate I am beginner in django I tried in all ways but not able to find solution
I was trying to upload a file and get a json response as ok using django rest framework
So far I tried is
views.py:
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import status
from .serializers import FileSerializer
class FileView(APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request, *args, **kwargs):
file_serializer = FileSerializer(data=request.data)
if file_serializer.is_valid():
file_serializer.save()
return Response(file_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
urls.py:
from django.conf.urls import url
from .views import FileView
urlpatterns = [
url(r'^upload/$', FileView.as_view(), name='file-upload'),
url(r'^upload/<int:pk>/$', FileView.as_view(), name='file-upload'),
]
The error is:
Method /GET/ is not allowed
please help me thanks in advance

If you can have a look at your view.py file, You don't have any GET method and this is why it is not able to call the URL with GET request.

Related

Specifying view function in Django

I'm practicing in Django and I want to know how requests and view mechanisms work correct in Django.
I started an app called ghcrawler in my django project. I designed like it has to send responses that recevied from localhost/ghcrawler and localhost/ghcrawler/results
So this is the urls.py in ghcrawler/ app folder.
from django.urls import path, include
from .views import main_view, results_view
urlpatterns = [
path('', main_view.as_view() , name='ghcrawler'),
path('ghresults', results_view.as_view(), name='getresults')
]
localhost/grcrawler page works well as expected. I just want to wire the requests coming to localhost/ghcrawler/results to getresults() function in results_view class defined in views.py, however it doesn't even write the 'h1' to the console
ghcrawler/views.py:
from django.views.generic import TemplateView
from django.shortcuts import render
from django import forms
from django.http import HttpResponse
from .github_requester import search_user
class main_view(TemplateView):
template_name = 'ghcrawler.html'
# Handle the post request received from /ghcrawler/
def post(self, request, *args, **kwargs):
if request.method == 'POST':
user = search_user(request.POST.get("username", ""))
if user == None:
print("User not found.")
else:
print(user)
return HttpResponse("OK")
class results_view(TemplateView):
template_name = 'ghresults.html'
def getresults(self, request, *args, **kwargs):
print('h1')
Rather than localhost/ghcrawler/results you mapped localhost/ghcrawler/ghresults to your view.
the rigth code would be:
urlpatterns = [
path('', main_view.as_view() , name='ghcrawler'),
path('results', results_view.as_view(), name='ghresults')
]
the firs argument in pathis the actual path
the secont argumen is the view
the third argument name is optional and used for addressing your view independant of your path
class results_view(TemplateView):
template_name = 'ghresults.html'
def get(self, request, *args, **kwargs):
print('h1')

Django rest framework error while uploading image, submitted data is not file

I am new to Django rest framework and when ever I try to do post request via Postman and python script itself it shows error
{'bloodbank_logo': ['The submitted data was not a file. Check the encoding type on the form.']}
But there is no error when I try to post image using django admin.
my models.py
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
# Create your models here.
class Bloodbanks(models.Model):
bloodbank_user=models.ForeignKey(User, on_delete=models.CASCADE)
fullbankname=models.CharField(max_length=80,blank=False,default='Null')
apositive=models.PositiveIntegerField()
anegative=models.PositiveIntegerField()
bpositive=models.PositiveIntegerField()
bnegative=models.PositiveIntegerField()
abpositive=models.PositiveIntegerField()
abnegative=models.PositiveIntegerField()
opositive=models.PositiveIntegerField()
onegative=models.PositiveIntegerField()
latitude=models.CharField(max_length=20,blank=False,default='Null')
longitude=models.CharField(max_length=20,blank=False,default='Null')
state = models.CharField(max_length=100)
district=models.CharField(max_length=20,blank=False,default='Null')
location=models.CharField(max_length=20,blank=False,default='Null')
website = models.CharField(max_length=100, blank=True)
bloodbank_logo=models.ImageField(blank=False)
bloodbank_description=models.CharField(blank=True,max_length=200)
bloodbank_phone=models.CharField(blank=True,max_length=10)
def __str__(self):
return self.fullbankname
my serializers.py
from rest_framework import serializers,reverse
from bloodbank_api.models import Bloodbanks
class BloodbankdataSerializer(serializers.ModelSerializer):
bloodbanks_user=serializers.PrimaryKeyRelatedField(source='user.username',read_only=True)
url = serializers.HyperlinkedIdentityField(
view_name='bloodbank-detail-id',
lookup_field='pk'
)
bloodbank_logo=serializers.ImageField
class Meta:
model=Bloodbanks
fields=['id','bloodbanks_user','fullbankname','apositive',
'anegative','bpositive','bnegative','abpositive',
'abnegative','opositive','onegative','latitude',
'longitude','state','district','location','website',
'bloodbank_logo','bloodbank_description','bloodbank_phone','url']
views.py
from bloodbank_api.models import Bloodbanks
from bloodbank_api.serializers import BloodbankdataSerializer
from rest_framework import status,mixins,generics
from rest_framework.parsers import FormParser, MultiPartParser,JSONParser
from rest_framework.response import Response
from django.contrib.auth.models import User
# Create your views here
#updatelistpostput by primary key
class BloodbankDataDetail(mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Bloodbanks.objects.all()
serializer_class = BloodbankdataSerializer
parser_class=(MultiPartParser,JSONParser, FormParser)
lookup_field = 'pk'
def get(self, request,*args, **kwargs):
id=kwargs.get('pk')
if id is not None:
return self.retrieve(request,*args, **kwargs)
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
print(args,kwargs)
return self.create(request, *args, **kwargs)
def perform_create(self, serializer):
serializer.save(bloodbank_user=self.request.user)
urls.py
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from bloodbank_api.views import BloodbankDataDetail
from django.conf import settings
from django.conf.urls.static import static
urlpatterns=[
path('bloodbank/',BloodbankDataDetail.as_view(),name='bloodbank-detail'),
path('bloodbank/<int:pk>/',BloodbankDataDetail.as_view(),name='bloodbank-detail-id'),
]
urlpatterns = format_suffix_patterns(urlpatterns)+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
the python script that i have used to post do post request
import requests
endpoint='http://127.0.0.1:8000/bloodbank/'
data={
"fullbankname": "Dirgahyu",
"apositive": '1',
"anegative": '1',
"bpositive": '1',
"bnegative": '1',
"abpositive": '1',
"abnegative": '1',
"opositive": '1',
"onegative": '1',
"latitude": "dhdhd",
"longitude": "hdhdd",
"state": "dhhd",
"district": "dhdhgd",
"location": "dhdhdhd",
"website": "jdjdjd",
"bloodbank_logo": "/Users/aayushdipgiri/aayu's code/opencv/cat.jpeg",
"bloodbank_description": "hahaha",
"bloodbank_phone": "hhdhddh"
}
get_response = requests.post(endpoint, json=data)
print(get_response.json())
First thing I notice is that you are not sending an image, you are sending a string. Try this instead to send the file via requests module.
"bloodbank_logo": open("/Users/aayushdipgiri/aayu's code/opencv/cat.jpeg", "rb"),
If this does not work, I would try using django's FileField instead, but I won't go into detail as the above should work or give you a different error message at least.

DRF Post to ViewSet without writing into Model

I've always written data into database when posting via Django Rest Framework endpoints. This time I would like to process received data and send it somewhere else without writing into DB. I switched from ModelViewSet to ViewSet, I can issue GET request OK but receiving Bad Request 400 when I curl or POST via DRF URL. Here's a working minimal code (removed need for authentication etc):
urls.py
from django.urls import path, include
from .views import ContactView
from rest_framework import routers
router = routers.DefaultRouter()
router.register('message', ContactView, basename='message')
urlpatterns = [
path('', include(router.urls)),
]
serializers.py
from rest_framework import serializers
class ContactSerializer(serializers.Serializer):
text = serializers.CharField(max_length=250)
views.py
from rest_framework.response import Response
from .serializers import ContactSerializer
from rest_framework import viewsets
class ContactView(viewsets.ViewSet):
def list(self, request):
return Response('Got it')
def create(self, request):
serializer = ContactSerializer(data=request.data)
if serializer.is_valid():
return Response(serializer.data)
else:
return Response('Invalid')
Would greatly appreciate your suggestions.
You can use GenericAPIView for get or post request and do some logic in validate method, for example do something with signals or edit something. Also u can use #detailt_route or #list_route for any ModelViewSet for write special url for instance, example for edit extra data.
how i did rarely:
in urls.py
urlpatterns = [
url('v1/message', ContactAPIView.as_view(), name='message'),
]
in view.py
class ContactAPIView(GenericAPIView):
serializer_class = ContactSerializer
permission_classes = ()
def post(self, request, *args, **kwargs):
serializer_class = self.get_serializer_class()
serializer = serializer_class(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
data = {"status": True}
return Response(data)
in serializers.py
class ContactSerializer(serializers.Serializer):
text = serializers.TextField()
def validate(self, attrs):
write some logic
you are getting this error because you are using Viewsets which uses DefaultRouter to register routers for you. What it does is that it creates 2 urls for your viewset
message
message/id
so in your current case; i.e. viewset you need to send some dummy number in your url to access this post function (which is not a good approach).
So, you should use any class which parent doesn't include ViewSetMixin (which gives functionality of Router Registration) like in your case inherit your view from these classes
ListModelMixin
CreateModelMixin
GenericAPIView

Return custom response to successful POST request in django rest framework

I want to return a custom response to the user when they hit the API with a POST request and it's a success. Here are the code snippets :
views.py
class BlogPostAPIView(mixins.CreateModelMixin,generics.ListAPIView):
# lookup_field = 'pk'
serializer_class = BlogPostSerializer
def get_queryset(self):
return BlogPost.objects.all()
def perform_create(self, serializer):
serializer.save(user=self.request.user)
def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs)
urls.py
app_name = 'postings'
urlpatterns = [
re_path('^$', BlogPostAPIView.as_view(),name='post-create'),
re_path('^(?P<pk>\d+)/$', BlogPostRudView.as_view(),name='post-rud'),
]
Right now it's returning the details of the post request as successful response, is there any way I can return some other response based on my own custom queryset?
You can write custom api on views.py. I want to for example;
from rest_framework.views import APIView
from rest_framework.response import Response
class Hello(APIView):
#csrf_exempt
def post(self, request):
content = "Hi"
type = "message"
return Reponse({"content":content,"type":type})
and than define url.
app_name = 'postings'
urlpatterns = [
re_path('^$', BlogPostAPIView.as_view(),name='post-create'),
re_path('^(?P<pk>\d+)/$', BlogPostRudView.as_view(),name='post-rud'),
re_path('^hello/$', Hello.as_view(),name='Hello'),
]
That's it.
Also you can manage permessions : https://www.django-rest-framework.org/api-guide/permissions/#setting-the-permission-policy
and you can use serializer on views : https://www.django-rest-framework.org/api-guide/serializers/#saving-instances

DRF - Method 'GET' not allowed

I'm trying to setup a class based view in Django Rest Framework.
This is my urls.py -
from django.conf.urls import patterns, include, url
from rest_framework.urlpatterns import format_suffix_patterns
from django.contrib import admin
from TidalDEV import views
admin.autodiscover()
urlpatterns = patterns('',
url(r'^test/(?P<pk>[0-9]+)/$', views.TESTXMLDetail.as_view()),
)
And this is my view -
import os, tempfile, zipfile
from django.shortcuts import render
from django.core import serializers
from django.core.serializers import serialize
from django.core.servers.basehttp import FileWrapper
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer, XMLRenderer
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from itertools import chain
from TAPI.renderers import *
from TAPI.models import *
from TAPI.serializers import JobdtlSerializer, JobmstSerializer, TrgjobSerializer, JobdepSerializer
class TESTXMLDetail(APIView):
permission_classes = (AllowAny,)
"""
Retrieve, update or delete a snippet instance.
"""
def get_object(self, pk):
try:
mst = Jobmst.objects.db_manager('AdmiralDEV').raw("""
query1""", [pk])
dtl = Jobdtl.objects.db_manager('AdmiralDEV').raw("""
query2""", [pk])
dep = Jobdep.objects.db_manager('AdmiralDEV').raw("""
query3""", [pk])
trg = Trgjob.objects.db_manager('AdmiralDEV').raw("""
query4""", [pk])
except Jobmst.DoesNotExist:
return HttpResponse(status=404)
def get(self, request, pk, format=None):
jobmststring = JobmstSerializer(mst)
jobdtlstring = JobdtlSerializer(dtl)
jobdepstring = JobdepSerializer(dep, many=True)
trgjobstring = TrgjobSerializer(trg, many=True)
jobmst_serialized = {'jobmst': jobmststring.data}
jobdtl_serialized = {'jobdtl': jobdtlstring.data}
jobdep_serialized = [{'jobdep':item} for item in jobdepstring.data]
trgjob_serialized = [{'trgjob':item} for item in trgjobstring.data]
jobgroup = jobmst_serialized, jobdtl_serialized, jobdep_serialized, trgjob_serialized
jobgroupresponse = TESXMLResponse(jobgroup)
return jobgroupresponse
When I run the URL all I get is the XML format but then it says -
<detail>Method 'GET' not allowed.</detail>
I've tried setting the permission class in the view as above and I've also put the following lines in my settings.py what gives?
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
You're getting this error because the DRF APIView doesn't have a get method (or a method for any HTTP request type actually).To get your code working you can either rename your get_object method to get (making sure you add the expected parameters request and format), or you can write a get method to return your response:
class TESTXMLDetail(APIView):
def get(self, request, pk, format=None):
return self.get_object(pk)
def get_object(self, pk):
...
...

Categories