31👍
Please Note: This solution is not for production configuration. This is merely a workaround for easier setup while development. Please refrain from using this in production configuration.
Install django-cors-headers through pip install django-cors-headers
Then, add in installed apps ‘corsheaders’.
Add the setting,
CORS_ORIGIN_ALLOW_ALL = True
and,
ALLOWED_HOSTS = ['*']
This should do the trick.
UPDATE
You’ll also need to add it to the middlewares,
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
25👍
The currently accepted answer potentially opens sites up to security risks:
Why does the error happen:
In order for your AJAX request to work well, there are two things that need to happen:
- The request has to be accepted by the server.
- The returned request must be accepted by the browser, so that the client-side can do something with it.
The error that the OP reports, indicates that the second part of this process is failing. This is because if the request is sent from domain that is different to the server returning the request, the browser won’t accept it unless the appropriate headers are set (that is, the server has given permission for the browser to read it).
How to fix it:
Now to fix this, we can use django-cors-headers
. This will add the apropriate headers, so that the browser accepts the returned response. To install run:
pip install django-cors-headers
and add it to your middleware:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
Now, you need to add the domain you are sending your AJAX request from, to the list of allowed domains:
CORS_ALLOWED_ORIGINS = [
"www.example.com",
"http://127.0.0.1:8000",
...
]
What about CORS_ORIGIN_ALLOW_ALL
?
Do not use this unless you have a specific need to. Setting this to true, will mean that, any origin will be able to make a request to your API, and get a response. Unless you are making a public API, you probably won’t need to do this. More likely you will only need to serve a single domain or a few domains (maybe you have a front-end, served from a different place to your API etc.)
If you are happy for any domain to access your API then you can set the following:
CORS_ORIGIN_ALLOW_ALL = True
If you do this, you will also need to set the following:
ALLOWED_HOSTS = ['*']
The reason for this, is Django will only accept certain hosts by default, so there’s no point setting CORS_ORIGIN_ALLOW_ALL = True
unless you’re actually going to accept requests from anyone (that is the part 1 in the explanation above).
Note that by setting allowed hosts to a wildcard, you open yourself up to HTTP host header attacks. Make sure you understand these, and have made sure you are not affected. You can read more about them in the django docs.
Also note: if you have not set your ALLOWED_HOSTS
and you are wondering why your requests are working, it is because when DEBUG=True
certain hosts are allowed automatically, http://127.0.0.1:8000
etc.
- [Django]-How to pass django rest framework response to html?
- [Django]-How do you detect a new instance of the model in Django's model.save()
- [Django]-Specifying limit and offset in Django QuerySet wont work
4👍
Using django-cors-headers
Start by installing django-cors-headers using pip
pip install django-cors-headers
You need to add it to your project settings.py file:
INSTALLED_APPS = (
##...
'corsheaders'
)
Next you need to add corsheaders.middleware.CorsMiddleware middleware to the middleware classes in settings.py
MIDDLEWARE_CLASSES = (
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.BrokenLinkEmailsMiddleware',
'django.middleware.common.CommonMiddleware',
#...
)
You can then, either enable CORS for all domains by adding the following setting
CORS_ORIGIN_ALLOW_ALL = True
Or Only enable CORS for specified domains:
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'http//:localhost:8000',
)
- [Django]-Django: For Loop to Iterate Form Fields
- [Django]-Django apps aren't loaded yet when using asgi
- [Django]-How do I install psycopg2 for Python 3.x?
2👍
UPDATE (12.12.22)
Just add to the package.json
file the following line:
"proxy": "http://localhost:8000"
OLD ANSWER
Based on Joe Sadoski’s great idea,
I suggest an improvement to his solution that also supports react hot-reload-on-changes:
(All other proposed solutions here do not work in chrome since the last upgrades in 2022)
version: '3.1'
services:
web:
image: nginx:latest
ports:
- 8080:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
command: [nginx-debug, '-g', 'daemon off;']
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
network_mode: host
restart: unless-stopped
My change here is: network_mode: host
Now the nginx.conf
looks like this:
events {}
http{
server {
listen 80;
server_name localhost;
// this block handle react hot-reload
location /sockjs-node {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
// this block handle API calls
location ~* /(accounts|api|admin) {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
// this block handle all the rest (react/statics...)
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Here I change the upstreams to point on localhost
so both react server and django should run on the host computer in ports 3000
and 8000
.
So, after docker-compose up
, manage.py runserver
, and npm start
, both apps are available at http://localhost
!
- [Django]-How do you detect a new instance of the model in Django's model.save()
- [Django]-PHP Frameworks (CodeIgniter, Yii, CakePHP) vs. Django
- [Django]-Why won't Django use IPython?
1👍
See Yinon_90’s answer for a better working version of this concept.
I wanted to propose a solution that does not require altering the behavior of the Django or React apps.
In production, you might want to serve both apps on the same domain/from the same server, under different paths. This wouldn’t cause any CORS conflict in production.
Of course, we want to debug Django and utilize React HMR & Dev tools while debugging. For this, I’ve spun up an nginx docker container:
docker-compose.yml
:
version: '3.8'
services:
web:
image: nginx:latest
ports:
- 8080:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
command: [nginx-debug, '-g', 'daemon off;']
environment:
- NGINX_HOST=localhost
- NGINX_PORT=80
nginx.conf
:
Django debug is on port 8000, React HMR is on port 3000. I’ve allowed three paths to go to the Django app, /accounts
, /api
, and /admin
. The rest goes to the React app (and into the React Router system)
events {}
http{
server {
listen 80;
server_name localhost;
location ~* /(accounts|api|admin) {
proxy_pass http://host.docker.internal:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://host.docker.internal:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
After docker-compose up
, manage.py runserver
, and npm start
, both apps are available at localhost:8000
!
- [Django]-Specifying limit and offset in Django QuerySet wont work
- [Django]-Django apps aren't loaded yet when using asgi
- [Django]-Why won't Django use IPython?
0👍
I had the same problem, It was quite funny I was getting 200 code and swagger was working correctly, but react didn’t work properly.
simply these require in the setting.py:
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
and for front:
const setCookie = async () => {
axios.get(`${process.env.REACT_APP_API_URL}/core/csrf-cookie/`, {
headers: { 'Authorization': null },
withCredentials: true,
}
).catch( () => {
console.log('Something went wrong!')
});
setCsrfToken(getCookie('csrftoken'))
console.log(csrfToken)
}
call setCookie in the useEffect and it should work.
and Don’t forget to build react and set STATICFILES_DIRS
- [Django]-PHP Frameworks (CodeIgniter, Yii, CakePHP) vs. Django
- [Django]-Passing STATIC_URL to file javascript with django
- [Django]-How to pass django rest framework response to html?
0👍
This is a solution for those who have set everything as required by django-cors-headers
but are still getting an error such as:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Well, the problem, at least in my case, was that django-cors-headers
did not recognize http://localhost:5173
for some reason. As we know localhost has the IP address 127.0.0.1
. So I changed the host address of my react server to explicitly use the IP address 127.0.0.1
. I was using react with vite so I did the following changes in my vite.confing.ts
to set a new domain:
export default defineConfig({
// ...
server: {
host: '127.0.0.1', // Set the host to 127.0.0.1
port: 5173, // Set the port to 5173
},
})
So the domain of my frontend server after that will be http://127.0.0.1:5173
.
Now you only have to add this new domain to CORS_ALLOWED_ORIGINS
in settings.py
and the error should be resolved.
CORS_ALLOWED_ORIGINS = [
'http://127.0.0.1:5173',
]
— End of solution —
Further information for context:
- OS: Windows 11
- API calls made using: axios.
- If you want to see the difference of
http://localhost:5173
andhttp://127.0.0.1:5173
try starting your frontend server using each of them and each time check how the system represents these domains behind the scene using the cmd commandnetstat -ano
.
- [Django]-Cannot access django app through ip address while accessing it through localhost
- [Django]-Using django-admin on windows powershell
- [Django]-How to pass django rest framework response to html?