django filefield returning localhost-prefixed URL - django

I'm trying not to specify the full path of the web app in the settings to make it as portable as possible.
However,
with MEDIA_URL="/media/", an URL returned from a Django FileField model is http://localhost/media/....
with MEDIA_URL="//example.com/media/", the URL returned is http://example.com/media/....
But the schema (http/s) and domain (example.com) should match those of the requesting page. How can I do this?
The Django app is served through Nginx in combination with Gunicorn.

It sounds like nginx and Django are not configured to pass and use http host name (e.g. X-Forwarded-Host header). This looks like a good answer - https://stackoverflow.com/a/58044808/6865

Related

Django behind reverse proxy ?next= issue

I have deployed a Django application behind an nginx reverse proxy. This proxy handles multiple Django applications
So the main url is for example https://www.example.com
and then I use the reverse proxy to redirect to the specific Django application using subdirectory
for example https://www.example.com/myapp
The problem is that if I logout from myapp and try to access a page that requires login the redirect link is wrong, instead of
https://www.example.com/myapp?next=/mainpage
it gives me
https://www.example.com/?next=/myapp/mainpage
which is wrong since "myapp" cannot listen to requests from https://www.example.com/
Is there any way I can force Django to understand that the default url is https://www.example.com/myapp and not https://www.example.com?
Thanks

Redirect domain to .com in django in url.py

I have a website in Django, hosted in Heroku.
I have 2 domains, registered in different places:
mysite.com and mysite.com.br
I don't want to be penalized by Google for having 2 domains with the same website, therefor I would like to redirect everyone who enters mysite.com.br to mysite.com.
I entered in the DNS mysite.com.br(Not hosted anywhere) CNAME mysite.com(hosted in Heroku), which makes the user actually access the Heroku content, but the url keeps the .BR ....
So the Heroku support told me to do the redirection in the application. In this case, what's the best practice to redirect? I would imagine to do that in the url.py, but how can I do that if the "path" doesnt read the domain?
Thanks.
You can't do this in the URLs. I would write some middleware to check the host via request.get_host and redirect if you're not on the canonical one.
In fact it looks like someone has already written this: django-enforce-host.

Django setting root url path for redirects

I have a project with the following components:
a single page backbone application for the web client
a django app for the api
nginx in front to direct requests to backbone and django
In my nginx conf, I direct the requests to django if the path starts with /api ,
otherwise, I serve the files directly (index.html and static files)
This setup works fine, the problem arises when django needs to redirect the url. Say, for instance, I request /api/users , as I have forgotten the trailing slash, django automatically redirects this, but instead of redirecting to /api/users/ , it redirects to /users/ as django does not know that I am hosting it on /api. How can I configure django to handle this redirect correctly?

How to deploy static website connecting to Django RESTful API?

First of all, google or SO search didn't help me: lots of tips regarding django's staticfiles, which I believe are not relevant here.
I have inherited a project consisting of:
Django backend in form of API returning JSON responses only;
standard Swampdragon deployment pushing realtime updates to frontend; very little configuration has been done here;
Frontend webapp built on Backbone and marionette.js, compiled and minified by Grunt.
My problem is: the frontend needs to know addresses for swampdragon and django servers; right now those values are hardcoded, so there is for example a Backbone model with lines like:
url: function() {
return App.BACKEND_URL+'settings/map';
}
Why hardcoded: backend can be served on any port or have a subdomain to itself; frontend is static and normally would be simply thrown into /var/www (for Apache) or would use some very simple nginx config. Both will be served from the same place, but there is no guarantee the port numbers or subdomains would match.
Idea number 1: try to guess what BACKEND_URL is from javascript, by taking window.location.host and appending standard port. That's hackish and error prone.
Idea number 2: move frontend to Django and make it ask for swampdragon credentials (they would be sent in the context of home view). Problem with that is, the frontend files are compiled by grunt. So where Django would kindly expect something like:
<script src="{% static 'scripts/vendor/modernizr.js' %}"></script>
I actually have
<script src="scripts/vendor/a8bcb0b6.modernizr.js"></script>
Where 'a8bcb0b6' is grunt's hash/version number and will be regenerated during next minification/build. Do I need to add additional logic to get rid of such stuff and copy grunt's output directory to django's static and template dirs?
Or is there another way to make this work, the right one, I am missing?
Your architecture is already clean, no need to make Django know about grunt or serve static files, and no need to use JS hacks to guess port numbers
Reverse Proxy
Use a reverse proxy like nginx or any other web server you like as a front end to both the static files and the REST API.
In computer networks, a reverse proxy is a type of proxy server that
retrieves resources on behalf of a client from one or more servers.
These resources are then returned to the client as though they
originated from the proxy server itself. (Wikipedia)
I will outline the important aspects without going into too much detail:
URL for the REST API
We make configs so that nginx will forward the API requests to Django
location /api {
proxy_pass http://127.0.0.1:8000; # assumes Django listens here
proxy_set_header Host $http_host; # preserve host info
}
So the above assumes your Django REST is mapped to /api and runs on port 8000 (e.g. you can run gunicorn on that port, or any other server you like)
http://nginx.org/en/docs/http/ngx_http_proxy_module.html
URL for our front end app
Next nginx will serve the static files that come out of grunt, by simply pointing it to the static folder
location / { alias /app/static/; }
The above assumes your static resources are in /app/static/ folder (like index.html, your CSS, JS etc). So this is primarily to load your BackboneJS app.
Django static files
Next step is not required, but if you have static files that you use with the Django app (static files that are generated with ./manage.py collectstatic, e.g. the django admin or the UI of Django REST Framework etc), simply map according to your Django settings.py STATIC_URL and STATIC_ROOT
location /static { alias /app/django_static_root/; }
/static and django_static_root being the STATIC_URL and STATIC_ROOT respectively
To sum up
So e.g. when you hit example.com/, nginx simply serves up the static files, then when a JS script makes REST call to /api, it gets trapped in the /api nginx location and gets forwarded to Django
End result is, example.com/ and example.com/api both hit the same front end web server, which proxies them to the right places
So there you have it, reserve proxying solves your ports and subdomain issues (and many others, like slow static files from Django and same-origin policies in web browsers and firewalls not liking anything besides default HTTP and HTTPS ports)

quick question: how to set *.domainname.com url in django

I know there are lots of example for how to set http://domainname.com/username
url. But how to set http://username.domainname.com url in django?
Thinking a way to have a unique url for each user as http://username.domain.com like http://garry.posterous.com/
Thanks
As the first step, you need to arrange your DNS server to serve the wildcard domain; this is completely outside Django.
When you managed to do that (i.e. dig garry.posterous.com succeeds), then simply check for the HTTP_HOST request variable in the django view routines.
see Using Subdomains with Django: http://www.rossp.org/blog/2007/apr/28/using-subdomains-django/