HttpRequest.is_ajax() is deprecated starting with version 3.1.
I want to return html if the page is requested from a browser and as JsonResponse if called from javascript or programmatically.
I am seeking guidance on how to do that.
https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpRequest.is_ajax
I did what arakkal-abu said but I also added
'X-Requested-With' header with the same value
ie. 'XMLHttpRequest'
to my request and it worked
Make sure to import this at the top
import re
from django.http import JsonResponse
from django.utils.translation import gettext_lazy as _
from django.conf.urls import handler404
You can have this inside your function/method to determine if from browser or ajax call
requested_html = re.search(r'^text/html', request.META.get('HTTP_ACCEPT'))
if requested_html:
# requested from browser, do as per your wish
# ajax call. Returning as per wish
return JsonResponse({
'detail': _('Requested API URL not found')
}, status=404, safe=False)
If you request to load a page from a browser, you would see in the network tab under the requested headers of that request, text/html is at the beginning of requested headers.

However, if you are making an ajax call from the browser, the requested headers has */* in the beginning. If you attach
Accept: application/json
in the header, then requested headers become this

From this, you can understand how the accept header is different in these cases.
have you tried to check HttpRequest.headers?
HttpRequest.is_ajax() depends on HTTP_X_REQUESTED_WITH header.
so you can check this header, if it is true it would be AJAX other wise it would be a request from a browser.
HttpRequest.headers['HTTP_X_REQUESTED_WITH']
Check HTTP_X_REQUESTED_WITH header
def sample_view(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
From the Release Notes of 3.1
The
HttpRequest.is_ajax()method is deprecated as it relied on a jQuery-specific way of signifying AJAX calls, while current usage tends to use the JavaScript Fetch API. Depending on your use case, you can either write your own AJAX detection method, or use the newHttpRequest.accepts()method if your code depends on the client Accept HTTP header.
Simply check the Content-Type header.
is_ajax = request.META.get("CONTENT_TYPE") == "application/json"
if is_ajax:
do_stuff()
Funny thing -- the quoted deprecation blurb only gets you halfway there. There's no indication of how you "use the new HttpRequest.accepts method" to replace HttpRequest.is_ajax -- not in the deprecation text, nor the documentation, nor the release notes.
So, here it is: if request.accepts("application/json")
(At least that's what worked for me.)
Instead of:
if request.is_ajax():
Helped me:
if request.headers.get('x-requested-with') == 'XMLHttpRequest':