Skip to content

Instantly share code, notes, and snippets.

@miraculixx
Last active January 12, 2019 02:09
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save miraculixx/6536381 to your computer and use it in GitHub Desktop.
Save miraculixx/6536381 to your computer and use it in GitHub Desktop.
To enable CORS support in django-tastypie, use the following code snipet. Then create your tastypie resources as a subclass of BaseCorsResource.Basic code courtesy Daniel Conzalez of http://codeispoetry.me/index.php/make-your-django-tastypie-api-cross-domain/.I added documentation and the post_list method.
'''
Add CORS headers for tastypie APIs
Usage:
class MyModelResource(CORSModelResource):
...
class MyResource(CORSResource):
...
Authors:
original source by http://codeispoetry.me/index.php/make-your-django-tastypie-api-cross-domain/
extensions by @miraculixx
* deal with ?format requests
* always return CORS headers, even if always_return_data is False
* handle exceptions properly (e.g. raise tastypie.BadRequests)
* provide two distinct classes for ModelResource and Resource classes
'''
from django.http.response import HttpResponse
from tastypie import http
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.resources import csrf_exempt
from tastypie.resources import Resource, ModelResource
import logging
class BaseCorsResource(Resource):
"""
Class implementing CORS
"""
def error_response(self, *args, **kwargs):
response = super(BaseCorsResource, self).error_response(*args, **kwargs)
return self.add_cors_headers(response, expose_headers=True)
def add_cors_headers(self, response, expose_headers=False):
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Headers'] = 'content-type, authorization'
if expose_headers:
response['Access-Control-Expose-Headers'] = 'Location'
return response
def create_response(self, *args, **kwargs):
"""
Create the response for a resource. Note this will only
be called on a GET, POST, PUT request if
always_return_data is True
"""
response = super(BaseCorsResource, self).create_response(*args, **kwargs)
return self.add_cors_headers(response)
def post_list(self, request, **kwargs):
"""
In case of POST make sure we return the Access-Control-Allow Origin
regardless of returning data
"""
#logger.debug("post list %s\n%s" % (request, kwargs));
response = super(BaseCorsResource, self).post_list(request, **kwargs)
return self.add_cors_headers(response, True)
def post_detail(self, request, **kwargs):
"""
In case of POST make sure we return the Access-Control-Allow Origin
regardless of returning data
"""
#logger.debug("post detail %s\n%s" (request, **kwargs));
response = super(BaseCorsResource, self).post_list(request, **kwargs)
return self.add_cors_headers(response, True)
def put_list(self, request, **kwargs):
"""
In case of PUT make sure we return the Access-Control-Allow Origin
regardless of returning data
"""
response = super(BaseCorsResource, self).put_list(request, **kwargs)
return self.add_cors_headers(response, True)
def put_detail(self, request, **kwargs):
response = super(BaseCorsResource, self).put_detail(request, **kwargs)
return self.add_cors_headers(response, True)
def method_check(self, request, allowed=None):
"""
Check for an OPTIONS request. If so return the Allow- headers
"""
if allowed is None:
allowed = []
request_method = request.method.lower()
allows = ','.join(map(lambda s: s.upper(), allowed))
if request_method == 'options':
response = HttpResponse(allows)
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
response['Access-Control-Allow-Methods'] = "GET, PUT, POST, PATCH"
response['Allow'] = allows
raise ImmediateHttpResponse(response=response)
if not request_method in allowed:
response = http.HttpMethodNotAllowed(allows)
response['Allow'] = allows
raise ImmediateHttpResponse(response=response)
return request_method
def wrap_view(self, view):
@csrf_exempt
def wrapper(request, *args, **kwargs):
request.format = kwargs.pop('format', None)
wrapped_view = super(BaseCorsResource, self).wrap_view(view)
return wrapped_view(request, *args, **kwargs)
return wrapper
#Base Extended Abstract Model
class CORSModelResource(BaseCorsResource, ModelResource):
pass
class CORSResource(BaseCorsResource, Resource):
pass
@doukasd
Copy link

doukasd commented Jun 11, 2014

For me this class was hiding any related resources from being returned when accessing a resource. I solved this by changing the base class of BaseCorsResource from Resource to ModelResource.

@miraculixx
Copy link
Author

Thanks for your feedback. It should work when using CORSModelResource instead of BaseCorsResource.

@marcelometal
Copy link

django-cors-headers is a good alternative

@singhprabhanshu
Copy link

please tell me the way i can implement the code. Is that code is written in api.py for tastypie like
from tastypie.authorization import Authorization
from tastypie import fields
from django.db import models
from tastypie.resources import ModelResource, ALL, ALL_WITH_RELATIONS
from .models import Guest
from jakhar.api import urlencodeSerializer, AdminApiKeyAuthentication, UserResource
from tastypie.authorization import DjangoAuthorization, ReadOnlyAuthorization

from django.http.response import HttpResponse
from tastypie import http
from tastypie.exceptions import ImmediateHttpResponse
from tastypie.resources import csrf_exempt
from tastypie.resources import Resource, ModelResource
import logging

class GuestResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user')
class Meta:
queryset = Guest.objects.all()
resource_name = 'guest'
allowed_methods = ['get', 'post', 'delete', 'put', 'patch']
filtering = {
'guest_fname': ALL,
'user': ALL_WITH_RELATIONS,
'guest_timestamp': ALL

    }

	limit = 0
	always_return_data = True
	authentication = AdminApiKeyAuthentication()
	authorization = Authorization()
	serializer = urlencodeSerializer()

class BaseCorsResource(ModelResource):
"""
Class implementing CORS
"""
def error_response(self, *args, **kwargs):
response = super(BaseCorsResource, self).error_response(*args, **kwargs)
return self.add_cors_headers(response, expose_headers=True)

def add_cors_headers(self, response, expose_headers=False):
    response['Access-Control-Allow-Origin'] = '*'
    response['Access-Control-Allow-Headers'] = 'content-type, authorization'
    if expose_headers:
        response['Access-Control-Expose-Headers'] = 'Location'
    return response    

def create_response(self, *args, **kwargs):
    """
    Create the response for a resource. Note this will only
    be called on a GET, POST, PUT request if 
    always_return_data is True
    """
    response = super(BaseCorsResource, self).create_response(*args, **kwargs)
    return self.add_cors_headers(response)

def post_list(self, request, **kwargs):
    """
    In case of POST make sure we return the Access-Control-Allow Origin
    regardless of returning data
    """
    #logger.debug("post list %s\n%s" % (request, kwargs));
    response = super(BaseCorsResource, self).post_list(request, **kwargs)
    return self.add_cors_headers(response, True)

def post_detail(self, request, **kwargs):
    """
    In case of POST make sure we return the Access-Control-Allow Origin
    regardless of returning data
    """
    #logger.debug("post detail %s\n%s" (request, **kwargs));
    response = super(BaseCorsResource, self).post_list(request, **kwargs)
    return self.add_cors_headers(response, True)

def put_list(self, request, **kwargs):
    """
    In case of PUT make sure we return the Access-Control-Allow Origin
    regardless of returning data
    """
    response = super(BaseCorsResource, self).put_list(request, **kwargs)
    return self.add_cors_headers(response, True)    

def put_detail(self, request, **kwargs):
    response = super(BaseCorsResource, self).put_detail(request, **kwargs)
    return self.add_cors_headers(response, True)
    
def method_check(self, request, allowed=None):
    """
    Check for an OPTIONS request. If so return the Allow- headers
    """
    if allowed is None:
        allowed = []
        
    request_method = request.method.lower()
    allows = ','.join(map(lambda s: s.upper(), allowed))

    if request_method == 'options':
        response = HttpResponse(allows)
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
        response['Access-Control-Allow-Methods'] = "GET, PUT, POST, PATCH"
        response['Allow'] = allows
        raise ImmediateHttpResponse(response=response)

    if not request_method in allowed:
        response = http.HttpMethodNotAllowed(allows)
        response['Allow'] = allows
        raise ImmediateHttpResponse(response=response)

    return request_method

def wrap_view(self, view):
    @csrf_exempt
    def wrapper(request, *args, **kwargs):
        request.format = kwargs.pop('format', None)
        wrapped_view = super(BaseCorsResource, self).wrap_view(view)
        return wrapped_view(request, *args, **kwargs)
    return wrapper

#Base Extended Abstract Model
class CORSModelResource(BaseCorsResource, ModelResource):
pass

class CORSResource(BaseCorsResource, Resource):
pass

@singhprabhanshu
Copy link

For the CORS:
pip install django-cors-headers
Go to django settings.py and then follow the given steps:
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',

...

]

CORS_ORIGIN_ALLOW_ALL = True

Thats done for CROS!!!!#

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment