Django URLs: URL Issues [duplicate] - django

Is there a way to check if a request is AJAX in Python?
The equivalent of PHP's $_SERVER['HTTP_X_REQUESTED_WITH'] == 'xmlhttprequest'?

If the AJAX framework sets the X-Requested-With header in its requests, then you will be able to use that header to detect AJAX calls. It's up to the client-side framework to do this.
Getting hold of the HTTP headers depends on your Python framework of choice. In Django, the request object has an is_ajax method you can use directly.

is_ajax() is deprecated since Django 3.1 (as of 28th May, 2021) as they stated that it depends on jQuery ways of sending request but since people use fetch method a lot to make call Ajax calls, it has become unreliable in many cases.
Usually, text/html is requested in the header in the first option in the browser when it just the loads the page. However, if you were making API call, then it would become */* by default, if you attach Accept: application/json in the headers, then it become
application/json
So, you can check easily if the request is coming from ajax by this
import re # make sure to import this module at the top
in your function
requested_html = re.search(r'^text/html', request.META.get('HTTP_ACCEPT'))
if not requested_html:
# ajax request it is

Check this how to check if request is ajax in turbogears
also this for how to do this in Django(it depends in your framework): How to check contents of incoming HTTP header request

Just in case someone can find this useful, the Sec-Fetch-Dest can hint if the request is an ajax call or not.
So one could have something like this:
is_ajax_call = all(
request.headers.get("Sec-Fetch-Dest", "")
not in secFetchDest for secFetchDest in ["document", "iframe"]
)

Related

Flask default http headers - Caching and more

I'm inquiring on Flask and was wondering what are the default values for things such as cache-control. I can't find information on any HTTP headers. Maybe I'm mistaken and it's the server software who takes care of this part.
Thanks
For your first question about Caching:
As Flask docs state
Flask itself does not provide caching for you, but Flask-Caching, an extension for Flask does.
So you can use Flask-Caching if you want to do caching for your website.
For your second question about http headers:
You can use request object to get different header values How to get http headers in flask? and use make_response to set custom headers.

Make multiple rest get requests and save output

I need to call a REST-ful webservice in using a GET method with some parameters and save the output of the same.
My first approach was to make some requests in JavaScript and log the output using console.log(), but the server doesn't allow CORS. So I can't make it that way.
I am pretty sure this might be a common thing but I can't seem to find a simple way to do it. What would be the simplest way to do it? Is there any software that would allow me to make an array, let's say with 100 parameters, save 100 calls or what would be a better way to do it? PHP script?
p.s. I can't activate CORS in the server, nor can I place code in the same domain. So far I have an example I can call in the browser and have the XML return.
As far as CORS is concerned, that has to do with the API you're running on not allowing requests to be made from a different domain. This could be fixed by allowing CORS in the API you are developing on.
CORS Link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
The other option would be to have your website on the same domain as the API.
Once you have done that, you can simply make multiple AJAX requests to the API.
AJAX HTTP GET example: HTTP GET request in JavaScript?
EDIT:
You might also have to enable CORS in the HTTP header of your request. This would have to be added to an AJAX request:
Access-Control-Request-Headers: x-requested-with
Here is a helpful link for jquery in particular: How to get a cross-origin resource sharing (CORS) post request working

PUT, GET ,POST ,DELETE methods using djangorest framework

I'm using django rest framework , I use the post and get methods and it works, but I didn't understand how to use PUT and DELETE, do I use it in the html forms like : method='PUT' ? but i read that the browsers assimilated it to a GET method , do I write fonctions in my code for PUT and DELETE??
-I read many articles about rest and restful and I didn't understand the difference between it some people says that its the same , and others no but dont clarify,when I use POST and GET can I say that it's RESTFUL
thank you
Unless there's been a recent development, HTML forms do not support PUT nor DELETE methods. (GET, POST, PUT, and DELETE methods are part of HTTP, not HTML, more on this topic in this question)
However you can send PUT and DELETE requests using an HTTP client, e.g. Python has a library called requests you can use to send requests. Or if you want to do so from the front-end, e.g. from a browser, you can use JavaScript lib capable of sending out HTTP requests (or the more recent fetch() that comes with modern browsers, or its polyfill for older browsers)
e.g.
>>> import requests
>>> req = requests.request('PUT', 'http://yourapi/resource')
<Response [200]>

How to send POST variable in POSTMAN

I can't get POSTMAN to send any post variables to my Django app. Suppose I have a post variable called 'report_request' and it has a value that is a JSON string. On the Django side I want to get request.POST['report_request'] and parse the JSON into a dictionary. But POSTMAN never seems to send the POST data. How exactly do I do this? Is there some magical header I need to send?
Doh! My bad. The URL I need to connect to is really HTTPS rather than HTTP, but I was specifying the URL as http://. Apparently if Postman is asked to connect to an HTTPS site using HTTP, it silently just drops all POST variables. How lovely. Anyway it was an easy fix, just change the http:// url to https:// and all is well.
Be sure to provide the POST data in the body (body tab) of the request and not in the parameters (params tab).
Otherwise, POSTMAN will interpret your POST request as being without data and on a url with GET parameters.
See these specifications about csrf if needed
Check if you're sending the csrf token, it's a security feature.
https://docs.djangoproject.com/en/1.8/ref/csrf/

Django-tastypie. Output in JSON to the browser by default

I see 'Sorry, not implemented yet. Please append "?format=json" to
your URL.'. I need always append string "?format=json". Can I make a
output in JSON by default?
Regards,
Vitaliy
From the tastypie cookbook, in order to change the default format, you need to override the determine_format() method on your ModelResource:
class MyResource(ModelResource):
....
def determine_format(self, request):
return 'application/json'
The above link demonstrates alternative methods of determining output format.
Also, I don't think a valid answer is essentially "You don't need this".
Edit
It appears GregM's answer is probably (I haven't tested it) the most correct with the new version of TastyPie, as per documentation putting the following in your settings.py will restrict the serialization output to json.
TASTYPIE_DEFAULT_FORMATS = ['json']
As of tastypie 0.9.13, if you do not need XML support you can disable it globally by setting TASTYPIE_DEFAULT_FORMATS to just ['json'] in your settings.py file. Requests should then default to JSON.
I've tested setting TASTYPIE_DEFAULT_FORMATS to ['json'] but it doesn't prevent the "Sorry not implemented yet" message when viewing the API from a browser.
I am able to make that warning go away by forcing the "Accept" header to 'application/json' in a middleware:
class TastyJSONMiddleware(object):
"""
A Django middleware to make the Tastypie API always output in JSON format
instead of telling browsers that they haven't yet implemented text/html or
whatever.
WARNING: This includes a hardcoded url path for /api/. This is not 'DRY'
because it means you have to edit two places if you ever move your API
path.
"""
api_prefix = '/api/'
def process_request(self, request):
if request.path.startswith(self.api_prefix):
request.META['HTTP_ACCEPT'] = 'application/json'
Tasytpie has the defaults set as 'application/json'. But that is overridden by Browser request.
According to Tastypie, the default is overridden by Request Header ACCEPT and your format specification in GET ie. ?format=json. When you send request from browsers, if you see the Request HTTP Header sent, its something like -
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
The application/xml overrides the default in Tastypie Resource. Therefore, either you can set Browser Header to have 'application/json' (Bad idea) or you just specify in GET.
If you hit the same API url using CURL, you will see the JSON output without specifying that in GET.
To examine/test your REST API, use a Rest client instead of a browser, preferably one that knows how to pretty print JSON. I use the Postman plugin for Google Chrome.
If you want pretty json in command line:
curl https://api.twitter.com/1.1/search/tweets.json | python -m json.tool