How to set charset header in Django 1.11 - django

we are using Django1.11 and we are having some problems because our header Content-Type does not contain the charset part set to UTF-8. Something like this:
Content-Type: application/json; charset=UTF-8
I want to fix that for all endpoints, so I have thought to include a middleware to run after all midlewares have been run. The problem is that I do not know if that's possible. Any ideas? Or alternative solutions?

You can write a custom middleware like this:
from django.utils.deprecation import MiddlewareMixin
class AllIsJsonMiddleware(MiddlewareMixin):
def process_response(self, request, response):
response['Content-Type'] = 'application/json; charset=UTF-8'
return response
But I don't recommend this. This converts all responses to JSON. Best use a framework like https://www.django-rest-framework.org/.
However, can use a standard view respone...
return HttpResponse(data, content_type='application/json; charset=UTF-8')
... or a custom decorator:
from functools import wraps
def json_response(function):
#wraps(function)
def wrap(request, *args, **kwargs):
response = function(request, *args, **kwargs)
response['Content-Type'] = 'application/json; charset=UTF-8'
return response
return wrap
#json_response
def my_view(request):
# ....

Related

allow post requests in django REST framework

I am creating a simple rest api using django REST framework. I have successfully got the response by sending GET request to the api but since I want to send POST request, the django rest framework doesn't allow POST request by default.
As in image(below) only GET,HEAD, OPTIONS are allowed but not the POST request
The GET and POST methods inside of views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from profiles_api import serializers
from rest_framework import status
# Create your views here.
class HelloApiView(APIView):
"""Test APIView"""
#Here we are telling django that the serializer class for this apiViewClass is serializer.HelloSerializer class
serializer_class = serializers.HelloSerializer
def get(self, request, format=None):
"""Retruns a list of APIViews features."""
an_apiview = [
'Uses HTTP methods as fucntion (get, post, patch, put, delete)',
'It is similar to a traditional Django view',
'Gives you the most of the control over your logic',
'Is mapped manually to URLs'
]
#The response must be as dictionary which will be shown in json as response
return Response({'message': 'Hello!', 'an_apiview': an_apiview})
def post(self,request):
"""Create a hello message with our name"""
serializer = serializer.HelloSerializer(data=request.data)
if serializer.is_valid():
name = serializer.data.get('name')
message = 'Hello! {0}'.format(name)
return Response({'message':message})
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
How to allow POST requests in django REST framework?
The problem with the code was, you have added the def post() after the return statement.
To solve, just correct your indentation level as below,
class HelloApiView(APIView):
def get(self, request, format=None):
return Response()
def post(self, request):
return Response()

How to disable IE11 cache in django REST

I have some Internet Explorer problems with my Angular 5 app, because in the
IE 11 my get-requests to a django-REST backend are cached by the browser.
I found a question suggesting to add special cache-control-headers to the response, but I didn't find a working answer how to do it with Django REST. All other browsers I have tested seem to work without problems.
Perhaps you could add the Cache-Control header to all responses using a middleware class.
class CacheControlMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
response['Cache-Control'] = 'no-cache'
return response
and then wire that into your settings.py
MIDDLEWARE = [
...
'your.app.CacheControlMiddleware',
...
]
Bear in mind that will apply to all views (all your ModelViewSets), which you may or may not want.
If you want to apply it only to specific view sets, you may be better to override the retrieve() and list() methods in your view sets where you can set the Cache-Control header on the Response. For more info on that see http://www.django-rest-framework.org/api-guide/generic-views/#mixins
I had the same problem.
Adding the 'Cache-Control' header to the response worked for me.
response = Response()
response['Cache-Control'] = 'no-cache'
An example views.py:
from rest_framework import status
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
def snippet_list(request):
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
response = Response(serializer.data)
response['Cache-Control'] = 'no-cache'
return response
The other answers have the right idea, but here is a slightly more refined solution.
def disable_cache_middleware(get_response):
def middleware(request):
response = get_response(request)
response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
return response
return middleware
The main difference here is that no-store and must-revalidate are included in the header as well. The Mozilla documentation on the header suggests this combination to prevent browser caching. You can read more about the extra header values there.
Secondly, I just find that the function-based middleware results in a bit less boilerplate than the class-based solution in this case.

Django : when client request http methods that are not defined in the view class

I am now learning django rest framework library. And when I read the tutorial I suddenly curious about that what will happen if client request http methods that are not defined in the view class. For example If I write the code like below
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
In this case I define the "get" and "post" methods in the View class. what if client request the "put" or "delete" methods than what happens? I read the django docs and it saids View class dispatch the http method by using dispatch(). But what is happening? Thanks in advance!
You can take a look at the source on Github. The dispatch method checks which HTTP verb was used, and calls the appropriate function, or returns 405 - Method not allowed status code when the verb is not valid/expected (http_method_not_allowed is a django built-in method in the base View class that just returns the 405 status code).
The relevant portion is pasted below:
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
Essentially the same thing is done in django's own views (dispatch in django.views.generic.View):
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
If you're ever developing with django's own view classes, "Classy Class-Based Views" is a very helpful resource.

Adding headers to django CBV

I want to add a X-Frame-Options header to Django CreateView. I need this because I'll be serving a form that will be loaded in iframe tags.
The problem is, there are several methods in django class-based views that return HttpResponse objects.
Is there a way to add the header to the responses without overwriting all those methods?
class MyView(CreateView):
def get(self, request, *args, **kwargs):
resp = super(MyView, self).get(request, *args, **kwargs)
resp['X-Frame-Options'] = ''
return resp
# Same would go for form_invalid, post, put, etc...
Okay, I fixed it. If you've encountered similar problem, here's how to do it.
You have to overwrite render_to_response method in same way I did with get in the example code above.
I tried the overwrite render to response method, but I wanted a solution that I could use for a whole chunk of urls mapped to several views, and not have to deal with overwriting the same method on several views.
I made a middleware class based off of django-cors-headers so I could allow iframe-ing of part of my django app. I keep a middleware.py in my main project directory and save a couple random middleware classes I have made there, like this one here and a ForceResponse Exception for example.
import re
from django import http
from django.conf import settings
class XFrameAllowMiddleware(object):
def process_request(self, request):
"""
If CORS preflight header, then create an
empty body response (200 OK) and return it
Django won't bother calling any other request
view/exception middleware along with the requested view;
it will call any response middlewares
"""
if (self.is_enabled(request) and
request.method == 'OPTIONS' and
"HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META):
response = http.HttpResponse()
return response
return None
def process_response(self, request, response):
if self.is_enabled(request):
response['X-Frame-Options'] = 'ALLOWALL'
return response
def is_enabled(self, request):
return re.match(settings.XFRAME_URLS_REGEX, request.path)
Add it to your MIDDLEWARE_CLASSES and configure the regex in your settings:
MIDDLEWARE_CLASSES = (
...
'your_django_app.middleware.XFrameAllowMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
)
XFRAME_URLS_REGEX = r'^/iframe_this_url/.*$'
from the django-cors-headers read.me:
CORS_URLS_REGEX: specify a URL regex for which to enable the sending of CORS headers; Useful when you only want to enable CORS for specific URLs, e. g. for a REST API under /api/.
Example:
CORS_URLS_REGEX = r'^/api/.*$'
Default:
CORS_URLS_REGEX = '^.*$'

Django: how to set content-type header to text/xml within a class-based view?

I'm trying to do it this way, but it doesn't work.
class MyView(View):
def options(self, request, *args, **kwargs):
"""
Handles responding to requests for the OPTIONS HTTP verb.
"""
response = http.HttpResponse()
if self.kwargs.has_key('xml'):
response['Content-Type'] = 'text/xml; charset=utf-8'
return response
You don't need to write additional code. Use TemplateResponseMixin and set content_type attribute to whatever you need:
class MyView(TemplateResponseMixin):
content_type='application/xml'
...
I think the key point is render_to_response in django.views.generic.base , whose code is this:
def render_to_response(self, context, **response_kwargs):
"""
Returns a response, using the `response_class` for this
view, with a template rendered with the given context.
If any keyword arguments are provided, they will be
passed to the constructor of the response class.
"""
response_kwargs.setdefault('content_type', self.content_type) # key
return self.response_class(
request=self.request,
template=self.get_template_names(),
context=context,
**response_kwargs
)
As for your case, May be you need this code:
class MyView(ListView):
def get(self, request, *args, **kwargs):
context = self.get_context_data()
if self.kwargs.has_key('xml'):
return self.render_to_response(context, content_type="text/xml; charset=utf-8")
return self.render_to_response(context)
I made a middleware class based off of django-cors-headers so I could allow iframe-ing of part of my django app. I keep a middleware.py in my main project directory and save a couple random middleware classes I have made there, like this one here and a ForceResponse Exception for example.
import re
from django import http
from django.conf import settings
class XFrameAllowMiddleware(object):
def process_request(self, request):
"""
If CORS preflight header, then create an
empty body response (200 OK) and return it
Django won't bother calling any other request
view/exception middleware along with the requested view;
it will call any response middlewares
"""
if (self.is_enabled(request) and
request.method == 'OPTIONS' and
"HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META):
response = http.HttpResponse()
return response
return None
def process_response(self, request, response):
if self.is_enabled(request):
response['X-Frame-Options'] = 'ALLOWALL'
return response
def is_enabled(self, request):
return re.match(settings.XFRAME_URLS_REGEX, request.path)
Add it to your MIDDLEWARE_CLASSES and configure the regex in your settings:
MIDDLEWARE_CLASSES = (
...
'your_django_app.middleware.XFrameAllowMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
)
XFRAME_URLS_REGEX = r'^/iframe_this_url/.*$'
from the django-cors-headers read.me:
CORS_URLS_REGEX: specify a URL regex for which to enable the sending of CORS headers; Useful when you only want to enable CORS for specific URLs, e. g. for a REST API under /api/.
Example:
CORS_URLS_REGEX = r'^/api/.*$'
Default:
CORS_URLS_REGEX = '^.*$'