I'm trying to request swagger of Django app from Django view. To clarify what I mean, this is an example:
#action(methods=['GET'], detail=False, permission_classes=[AllowAny])
def get_swagger(self, request, *args, **kwargs):
try:
be_url = "http://localhost:8000/?format=openapi"
r = requests.get(be_url)
except Exception as e:
return Response('data': str(e))
return Response('data': r.json())
But when I request this endpoint response goes very long and then fails with a 404.
Related
Is it possible to write a class based (not function) custom error page handler?
for example this:
def handler404(request, *args, **argv):
response = render_to_response('404.html', {},
context_instance=RequestContext(request))
response.status_code = 404
return response
but with class
I have a Django module which is called from an SSO service. The service has a single signout function which makes a single GET request to a URL given to it during login.
I'm trying to set up an APIView in Django to handle this logout. The origin service never checks the response; it only calls the GET URL once.
I'm trying something like this for the APIView but keep getting session.DoesNotExist exceptions:
class LogoutApi(APIView):
def get(self, request, *args, **kwargs):
s = Session.objects.get(session_key=kwargs.get('sk', ''))
s.delete()
return Response({'result': True})
I know I have a valid session but even when I try iterating through the Session.objects I can't find it.
I also tried pulling the key from the SessionStore:
class LogoutApi(APIView):
def get(self, request, *args, **kwargs):
sk = request.GET.get('sk', '')
try:
s = SessionStore(sk)
del s[sk]
return Response({'result': True})
except:
self.logger.error(sys.exc_info()[0])
return Response({'result': False})
It still wasn't successful. Is there a way I can set up a GET API call to terminate a specific session?
Turns out the issue was that the session engine was set to use signed cookies. After I removed the following line from my configuration, all worked as expected:
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" # Removed this line
For reference, this is the logout code that worked with the above setting:
class LogoutApi(APIView):
def get(self, request, *args, **kwargs):
sk = request.GET.get('sk', '')
if sk:
s = SessionStore(session_key=sk)
s.delete()
return Response({'result': True})
return Response({'result': False})
Im trying to raise a 400 exception when the user does not provide a token or when the token is not valid my code is below :
this is my exceptions.py file :
from rest_framework.exceptions import APIException, PermissionDenied
class MissingTokenException(APIException):
status_code = 400
default_detail = 'Your request does not contain token'
default_code = 'no_token'
class InvalidTokenException(APIException):
status_code = 400
default_detail = 'Your request contain invalid token'
default_code = 'invalid_token'
this is my views.py file :
class ListProductsOfCategory(generics.ListAPIView):
serializer_class = ProductSerializer
lookup_url_kwarg = 'category_id'
def dispatch(self, *args, **kwargs):
token = self.request.META.get("HTTP_TOKEN", "")
if not token:
# here I wan to raise an error saying that no token provided.
raise MissingTokenException
if not UserAccess.objects.filter(accessToken=token).exists():
# here I wan to raise an error saying that token provided is not valid.
raise InvalidTokenException
return super().dispatch(*args, **kwargs)
def get_queryset(self):
category_id = self.kwargs.get(self.lookup_url_kwarg)
return Product.objects.filter(category_id=category_id)
Im using postman to test my APIs:
please if any one can help Im new to django and python.
DRF handles most of its internals within the dispatch function, including catching the APIException.
If you want to raise an APIException outside of it - which is what your code is doing - you'll also have to catch the exception and call the exception handler as does DRF.
Please also note that you would miss content negotiation and a few other things.
A better way to deal with it is to perform the check though authentication and permissions.
I have a generic class based view:
class ProjectDetails(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
generics.GenericAPIView):
queryset = Project.objects.all()
# Rest of definition
And in my urls.py, I have:
urlpatterns = [
url(r'^(?P<pk>[0-9]+)/$', views.ProjectDetails.as_view())
]
When the API is called with a non-existent id, it returns HTTP 404 response with the content:
{
"detail": "Not found."
}
Is it possible to modify this response?
I need to customize error message for this view only.
This solution affect all views:
Surely you can supply your custom exception handler: Custom exception handling
from rest_framework.views import exception_handler
from rest_framework import status
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# Now add the HTTP status code to the response.
if response.status_code == status.HTTP_404_NOT_FOUND:
response.data['custom_field'] = 'some_custom_value'
return response
Sure you can skip default rest_framework.views.exception_handler and make it completely raw.
Note: remember to mention your handler in django.conf.settings.REST_FRAMEWORK['EXCEPTION_HANDLER']
Solution for specific view:
from rest_framework.response import Response
# rest of the imports
class ProjectDetails(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
generics.GenericAPIView):
queryset = Project.objects.all()
def handle_exception(self, exc):
if isinstance(exc, Http404):
return Response({'data': 'your custom response'},
status=status.HTTP_404_NOT_FOUND)
return super(ProjectDetails, self).handle_exception(exc)
It's possible by overriding specific methods like update, retrieve as:
from django.http import Http404
from rest_framework.response import Response
class ProjectDetails(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
generics.GenericAPIView):
queryset = Project.objects.all()
def retrieve(self, request, *args, **kwargs):
try:
return super().retrieve(request, *args, **kwargs)
except Http404:
return Response(data={"cusom": "message"})
def update(self, request, *args, **kwargs):
try:
return super().update(request, *args, **kwargs)
except Http404:
return Response(data={"cusom": "message"})
My Django Rest API views.py:
# encoding: utf-8
from fileupload.response import JSONResponse, response_mimetype
from fileupload.models import *
from rest_framework.views import *
from rest_framework.parsers import *
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
"""A simple API for file upload."""
class FileUploadView(APIView):
authentication_classes = ()
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(FileUploadView, self).dispatch(request, *args, **kwargs)
def put(self, request):
print "xxx:", request
try:
psfile = MyFile.objects.create(file=request.FILES['file'])
psfile.save()
data = {'files': 'testing'}
response = Response(data)
except Exception as e:
print "Exception when put file:", e
data = { 'error' : str(e)}
response = Response(data)
return response
setting.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ()
}
I am doing PUT in Postman with Postman Interceptor enabled.
Tried to put the file in the body as form-data.
But failed with the following error:
Could not get any response
There was an error connecting to https://ip/projectname/api/upload/.
Why this might have happened:
1. The server couldn't send a response:
Ensure that the backend is working properly
2. SSL connections are being blocked:
Fix this by importing SSL certificates in Chrome
3. Cookies not being sent: Use the Postman Interceptor extension
4. Request timeout:
Change request timeout in Settings > General
Any ideas? Thanks in advance.
UPDATE
https://github.com/postmanlabs/postman-app-support/issues/506
http://blog.getpostman.com/2014/01/28/using-self-signed-certificates-with-postman/