Uploading and Downloading Files with Django and Nginx - python

I'm currently trying to upload some files using Django and it seems to be working for the most part. I'm at least able to see that the file is added to the specific model in the Django admin panel but I'm unable to open it. Additionally, whenever I try to get the URL of the file, I get forwarded to the Django error page with a nice error that says, [Errno 2] No such file or directory: 'media/some_file.csv'
Here is my file model :
class File(models.Model):
challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE, default="")
file = models.FileField(default="", upload_to="media/")
def __str__(self):
return self.challenge.challenge_id
Settings.py :
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'server', 'static'),
os.path.join(BASE_DIR, '..', 'media'),
)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = 'media/'
Upload Function :
def uploadChallengeFile(request):
latestChallenge = Challenge.objects.last()
for file in request.FILES.items():
file_model = File(challenge=latestChallenge, file=file[0])
file_model.save()
data = {"data": [True]}
return JsonResponse(data, safe=False)
Download Function :
def downloadFile(request, challenge_id):
challenge = Challenge.objects.filter(challenge_id=challenge_id)
filename = File.objects.filter(challenge=challenge).values("file")[0]["file"]
content = open(File.objects.get(challenge=challenge).file.url).read()
response = HttpResponse(content, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
urls.py :
url(r'^api/start/download/(?P<challenge_id>[\w.#+-]+)/$', views.backendServices.downloadFile, name="download")
It seems like Django is saving the instance of the file but not actually storing it. Do I need to configure the nginx.conf to serve the files from the /media directory or do something else? Any help would be greatly appreciated.
Thanks

Generally you have to configure nginx to proxy pass requests to media/ and static/ to your django instances:
The following assumes your django service can be reached at http://django:8000, but more likely if you're not using docker (and it's not named django), it would be http://localhost:8000
location /static {
proxy_pass http://django:8000;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location /media {
proxy_pass http://django:8000;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
Also, make sure when running in DEBUG mode (normally local dev) set the URL routes so django handles them
if settings.DEBUG:
from django.views.static import serve
from django.conf.urls.static import static
urlpatterns += [
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Related

Flask Redirect Creates Invalid URL with Nginx and Certbot

I have done a ton of research and altered the code to try to fix this but nothing is working. Flask route redirection is now working properly with Nginx and Certbot. Getting to the website works fine , clicking a link in the navigation works fine, but when Flask tries to redirect to another URL (Flask route) it creates a invalid URL that looks like this:
https://example.com/signup
After submitting the form (POST) request this is what I see for the URL.
https://example.com,example.com/login
Here is the Flask Python code:
#main.route('/signup', methods=['GET', 'POST'])
def sign_up():
'''sign up user'''
form = SignupForm()
if form.validate_on_submit():
return redirect(url_for('main.login'))
return render_template('main/signup.html', form=form)
#main.route('/login', methods=['GET', 'POST'])
def login():
'''login user'''
form = LoginForm()
if form.validate_on_submit():
pass
return render_template('main/login.html', form=form)
The Nginx website configuration:
server {
server_name example.com www.example.com;
location / {
include proxy_params;
proxy_pass http://unix:/var/www/example/example.sock;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
If I type this manually it works, which means that the Python/Flask code is okay.
https://example.com/login
The solution is in the Nginx location block. Notice the line include proxy_params;. It ended up including the same information twice.
location / {
include proxy_params;
proxy_pass http://unix:/var/www/example/example.sock;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
}
Since the file /etc/nginx/proxy_params included the proxy_set_header information I did not have to add it again. The location block now looks like this.
location / {
include proxy_params;
proxy_pass http://unix:/var/www/example/example.sock;
}

Django admin dashboard CSS is missing

I just deployed my application to DigitalOcean. Everything works very well, excep admin panel's styling although I've used nginx. Here are my codes:
settings.py:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static_root")
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
nginx configuration:
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static_root/ {
root /home/my_username/myproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/my_username/myproject/myproject.sock;
}
}

How to configure static and media files with django and nginx?

I have next settings.py on my local server.
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_root")
MEDIA_URL = '/media/'
MEDIA_ROOT= os.path.join(os.path.dirname(BASE_DIR), "media_root")
I know that in production Nginx should handle static and media. Okay.
I use gunicorn and supervisor on my prod server.
My nginx config:
server {
listen 8000;
server_name 194.87.95.46;
access_log /var/log/nginx/example.log;
location /static {
alias /home/split/static_root/;
}
location /media {
alias /home/split/media_root/;
}
location / {
proxy_pass http://127.0.0.1:8003;
proxy_set_header Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
But nginx doesnt handle static and media, what's the problem?
I think your issue is caused by trailing slashes - you haven't provided a trailing slash in the location definition, but you have in the alias. Try this instead:
location /static/ {
alias /home/split/static_root/;
}
location /media/ {
alias /home/split/media_root/;
}

Static Files not being displayed in Production

EDITED TO SHOW UPDATED CONFIGURATION
No static files are being shown in Production. Files are showing correctly in Development
settings.py
BASE_DIR = os.path.dirname(__file__)
STATIC_ROOT = '/opt/soundshelter/static/'
print "Base Dir: " + BASE_DIR #this returns /opt/soundshelter/soundshelter/soundshelter
print "Static Root: " + STATIC_ROOT #this returns /opt/soundshelter/static/
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
) #/opt/soundshelter/soundshelter/soundshelter/static
Files are being called in the applications with
<link href="{% static "css/portfolio-item.css" %}" rel="stylesheet">
Using Nginx and Gunicorn.
Nginx config:
server {
server_name 46.101.56.50;
access_log yes;
location /static {
autoindex on;
alias /opt/soundshelter/static/;
}
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
}
# error_log /opt/soundshelter/soundshelter/soundshelter/nginx-error.log;
}
Running python manage.py collectstatic reports files were successfully copied but are still not being displayed.
Deployment handled by Fabric
from __future__ import with_statement
from fabric.api import *
from fabric.contrib.console import confirm
env.hosts = []
print "Here we go..."
def commit():
local("git add . && git commit")
def push():
local("git push origin master")
def prepare_deploy():
commit()
push()
def deploy():
code_dir = '/opt/soundshelter/soundshelter/'
with cd(code_dir):
run("git pull")
run("python manage.py collectstatic -v0 --noinput")
run("service nginx restart")
run("ps aux |grep gunicorn |xargs kill -HUP")
run("gunicorn -b PROD_IP soundshelter.wsgi:application")
commit()
push()
deploy()
First of all, it seems to me that your edited STATICFILES_DIRS points to the wrong folder, since you have /static/ folder, not /staticfiles/. Should be as it was originally:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
Second, STATIC_ROOT should point to the static folder which will be served by webserver in pro (but preferably not in project folder). In your case:
STATIC_ROOT="/opt/soundshelter/soundshelter/soundshelter/static/"
I usually place static folder near the project one and use dynamic STATIC_ROOT instead of hardcoding:
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
#this will alow to collect your static files in /opt/soundshelter/soundshelter/staticfiles/static
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'staticfiles/static')
Now you should do collectstatic and it will collect all static files in the STATIC_ROOT directory.
In your Nginx Config did you try to set:
location /static {
instead of
location /static/ {
also make sure the user running nginx has read permissions to the static folder.
BAD SOLUTION - DO NOT USE IN PRODUCTION
https://docs.djangoproject.com/en/1.8/howto/static-files/
Adding this to urls.py did the trick
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Django won't recognize my static files on my dev machine

I've been tasked with fixing some aspects of a django 1.3 site, that runs on Apache/PostgreSql on the server. I'm trying to set it up on my development machine, with a virtual environment with postgres and the internal python developer server.
I managed to get the site running and reading from my local pg instance, but I can't get it to recognize my static files, which are stored in /site_media. The site will soon be rewritten to use django 1.6 and the proper /static folder but for now I need to fix this site.
I also tried running it with nginx and gnunicorn but the result is the same, the site displays but with no style and all references to files in the static dir give a 404. further inspection of the 404 reveals that django is trying to resolve the resources with its router.
Here are the relevant settings:
settings.py:
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = '/home/nico/src/df2/datos/site_media/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = 'http://localhost:8000/site_media/'
I also added the following config, to no avail:
INSTALLED_APPS = (
'django.contrib.staticfiles',
)
STATICFILES_DIRS = (
'/home/nico/src/df2/datos/site_media/',
)
STATIC_URL = 'http://localhost:8000/site_media'
nginx config file:
server {
server_name localhost;
access_log off;
location /site_media/ {
alias /home/nico/src/df2/datos/site_media;
}
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
}
}
If you need any other config please tell me.
I'd prefer to run this purely from the python server, but a solution with gunicorn/nginx is also fine
The fix was in adding a static handler to the urlpatterns variable:
from django.conf import settings
if settings.DEBUG:
# static files (images, css, javascript, etc.)
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT}))

Categories

Resources