-
-
Save miraculixx/6536381 to your computer and use it in GitHub Desktop.
''' | |
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 |
Thanks for your feedback. It should work when using CORSModelResource instead of BaseCorsResource.
django-cors-headers is a good alternative
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
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!!!!#
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.