django-sample-app icon indicating copy to clipboard operation
django-sample-app copied to clipboard

Serving static files

Open eddo87 opened this issue 8 years ago • 3 comments

Hi there,

this is more a newbie question but after many hours spent troubleshooting, and found many un resolved questions on StackOverflow I thought I might ask!

First of all props for the project, as it's very useful for someone that wants to start on django!

On the Sys admin side, as I would like to have a production website in the future and I'm testing it.

Why while serving the website through Nginx and uWSGI, pointing to the static correctly I still see a "broken" (of css and js) site?

at first I had the nginx config wrong, now I get no errors but still can't see the website properly.

Do I have to delete local.py and just keep default.py? are there any specific permissions to be added? Everything is run and owned by www-data, socket permissions on 774 Thanks a lot!

here some info of the setup

manage.py collectstatic

You have requested to collect static files at the destination location as specified in your settings: /home/django/sample/static

root@bananapi /home/django # tree -d sample sample ├── media ├── sample │   ├── home │   └── settings ├── static │   ├── admin │   │   ├── css │   │   ├── img │   │   │   └── gis │   │   └── js │   │   └── admin │   ├── CACHE │   │   ├── css │   │   └── js │   ├── css │   ├── django_extensions │   │   ├── css │   │   ├── img │   │   └── js │   ├── images │   ├── js │   ├── libs │   │   ├── bootstrap-3.3.5 │   │   │   ├── css │   │   │   ├── fonts │   │   │   └── js │   │   ├── font-awesome-4.3.0 │   │   │   ├── css │   │   │   ├── fonts │   │   │   ├── less │   │   │   └── scss │   │   ├── jquery │   │   │   └── 2.1.0 │   │   └── modernizr │   │   └── 2.6.2 │   └── media ├── static-assets │   ├── css │   ├── images │   ├── js │   ├── libs │   │   ├── bootstrap-3.3.5 │   │   │   ├── css │   │   │   ├── fonts │   │   │   └── js │   │   ├── font-awesome-4.3.0 │   │   │   ├── css │   │   │   ├── fonts │   │   │   ├── less │   │   │   └── scss │   │   ├── jquery │   │   │   └── 2.1.0 │   │   └── modernizr │   │   └── 2.6.2 │   └── media -> ../media/ └── templates

nginx.conf

upstream sample { server unix:/home/django/sample/sample.sock; }

server { listen 80; server_name bananapi; access_log off;

    location /static/ {
       alias /home/django/sample/static/;
    }

    location /media/ {
       alias /home/django/sample/media/;
    }

    location / {
       root /home/django/sample;
       uwsgi_pass   sample;
       include /etc/nginx/uwsgi_params;
       uwsgi_send_timeout 300;
       uwsgi_read_timeout 300;
       proxy_pass http://unix:/home/django/sample/sample.sock;
       proxy_set_header Host $host;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

eddo87 avatar Jun 26 '16 17:06 eddo87

Well, without explicit testing I can tell there is a few different minor issues with your media files configuration and I also believe you found a bug for the same topic. I actually would like to know if your application has any media files (such as user uploads, avatars etc) because they seem to be the displaying issues. Let's go one by one:

  • Yes, you should not have any local.py file in your production system unless you are experimenting any machine specific or doing development, staging etc. Intending to have a local.py basically means that you want to over-write your default.py. Maybe I should rename it to production.py.
  • What are your settings for MEDIA_URL and MEDIA_ROOT in your default.py? Because the current version has MEDIA_URL = STATIC_URL + 'media/', you should match this static URL settings in your nginx location. So with the default settings your media path should be /static/media/ in nginx or feel free to change your settings to match your /media/ pattern.

And the bug I was talking about, your media directory in nginx perfectly points to where the application default settings points, just under its root directory. I am not sure at this point if nginx matches these prefix patterns with the first-match basis or if there is a kind of longest-length matching prefix algorithm but if a developer choose to stick to default /static/media/ style, then (s)he may have to define the media location in their nginx before their static location definition so it can be matched first.

Besides this ambiguity, there is also another static/media (/home/django/sample/static/media) subdirectory that is created on the fly when you do collectstatic. This folder sounds like just a duplicate version of original media directory at the time of doing collectstatic. The package is absolutely not obvious about how the media folder configuration should be after all, apologises.

For this case you can easily resolve it either by:

  • Stick to /media/ as in your nginx and fix your default.py so you won't have any prefix ambiguity at all. Then this media subfolder under your collected static will become redundant and will copy your original media every time you do deployment and so collectstatic.
  • Or if you like the URL /static/media/, you can actually remove your media location definition in your nginx config and manually convert that static/media subfolder to a symbolic link once, pointing relatively to ../media. So whenever your admin or application uploads any file, they will still go to original media folde, will be displayed via /static/ prefix in your nginx and media symbolic link back to original media folder.

Thanks for raising these issues. I will leave this issue open until it gets obvious about managing media files, even though there is little space to blame django-compressor package too.

kirpit avatar Jun 28 '16 06:06 kirpit

Thanks for your reply, I do grasp more how it works, but I was unable to overcome the issue.

I've not edited nor added anything to your sample app. I'm just testing in a Intranet environment how to deploy it, that it will work as if i would runserver .

So I made the /static/media a link to /home/django/sample/media which is served in the nginx config at the same level of /static/ (anything wrong with the fact that there is only an empty init.txt file in /media/ ?)

I renamed the local.py and edited the default.py

STATIC_ROOT = '%s/static' % ABS_PROJECT_ROOT Absolute filesystem path to the directory that will hold user-uploaded files. MEDIA_ROOT = '%s/media' % ABS_PROJECT_ROOT

The URL that handles the media, static, etc. STATIC_URL = 'bananapi/' MEDIA_URL = STATIC_URL + 'media/'

In this URL section I tried, with and without STATIC_URL

I still think it's more of a knowledge issue and guides online don't take this step into details, much appreciation for your support!

eddo87 avatar Jun 28 '16 14:06 eddo87

Hello, I had the same issue from here and it appears setting DEBUG=True in settings/default.py fixed the problem

I can't really understand why as I'm not familiar to django but an explaination is welcome

gogaz avatar Jan 09 '17 22:01 gogaz