2
votes

I've seen lots of different posts regarding the Django static file issues. Unfortunately, none of them seem to help me. My django admin css is fine, however static files are giving my a 404 error. Here is a description of what my problem:

In settings.py:

STATIC_URL = '/static/'
STATIC_ROOT = '/Users/me/develop/ember/myproj/static/'

In urls.py:

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

My project directory:

> static
  > myproj
    > app
      > templates
        > ember.hbs
    > img
      > test.jpg

Inside my ember.hbs I reference the test.jpg, but I get a 404 error. It's weird because I can actually pull up the image using:
file:///Users/me/develop/ember/proj/static/myproj/img/test.jpg

I have no idea what to do to fix this, I've tried using the STATICFILES_DIRS method mentioned here: https://docs.djangoproject.com/en/1.8/howto/static-files/ but nothing seems to be working.

Thanks in advance!

More information: Django 1.8 and Ember-CLI. I'm hosting the ember project within the static dir.
I'm running python manage.py runserver and running django on port 8000 at the same time as running ember s and running the application on port 4200. I'm using CORS-headers (https://github.com/ottoyiu/django-cors-headers/) to allow cross-site calls on development.

3
Are you using /static/myproj/img/test.jpg in your html to load this file ? - cafebabe1991
1) What is URL to that test.jpg when django project (get full path from view source), 2) Are you running django with Apache or some other server? - Krishna Sunuwar
Yes @cafebabe1991, I'm using exactly that in my ember.hbs. - atschaal
@KrishnaSunuwar 1) The url from source: "NetworkError: 404 Not Found - localhost:4200/static/myproj/img/test.jpg" 2) I'm running the django project on localhost:8000 and using CORS headers (github.com/ottoyiu/django-cors-headers) to allow cross server calls on my development environment. - atschaal

3 Answers

0
votes

Ember and Django really shouldn't live in the same project. They are completely different frameworks with different tooling.

Think of your Django project as the backend application that serves an API. Think of your Ember project as one of possibly many clients that will consume your API. Others might include mobile applications, partner services, and so on.

When I start a new project that is going to use Django and Ember, I start a Django project called "myproject":

django-admin.py startproject myproject

And separately, an Ember project called "myproject-web":

ember new myproject-web

In development, I'll have two tabs open in Terminal.

First tab:

cd myproject
./manage.py runserver

Second tab:

cd myproject-web
ember serve

In production, I'll have two different servers, one at app.myproject.com that serves the Django application, and another one at myproject.com that serves the Ember application.

Later on, I might start a Swift project in a repository called "myproject-ios", and a Java project called "myproject-android". You get the idea.

1
votes

Static files will be discovered in "apps" that you create (found in INSTALLED_APPS) or in additional directories that you specify in STATICFILES_DIRS.

Let's say I did:

django-admin.py startproject myproject

And then:

cd myproject
./manage.py startapp myapp
mkdir myapp/static
mkdir myproject/static

Would give you a directory structure that looks something like

/Users/me/develop/myproject/
  > myapp/
      > migrations/
      > static/
      > __init__.py
      > admin.py
      > models.py
      > tests.py
      > views.py
  > myproject/
      > static/
      > __init__.py
      > settings.py
      > urls.py
      > wsgi.py
  > manage.py

And then in settings.py you add "myapp" to INSTALLED_APPS.

In this structure, myapp/static/ files will be automatically discovered by Django because it is an installed app with a static directory. However, myproject/static/ files will NOT be discovered automatically because "myproject" is not in INSTALLED_APPS (and it shouldn't be).

This is because of the default STATICFILES_FINDERS setting, which is:

STATICFILES_FINDERS = [
  'django.contrib.staticfiles.finders.AppDirectoriesFinder',
  'django.contrib.staticfiles.finders.FileSystemFinder',
]

The first finder, AppDirectoriesFinder, scans the directories of all of your INSTALLED_APPS, and discovers any "static" folders they might contain.

The second finder, FileSystemFinder, scans extra directories that you specify in STATICFILES_DIRS, which is an empty list by default.

So if you want those files in /Users/me/develop/myproject/myproject/static/ to be discovered (as you probably do), you can add this to your settings.py:

from os import pardir
from os.path import abspath, dirname, join

# Get the root directory of our project    
BASE_DIR = abspath(join(dirname(__file__), pardir))

# Add our project static folder for discovery
STATICFILES_DIRS = (
    # /Users/me/develop/myproject/myproject/static/
    join(BASE_DIR, 'myproject', 'static'),
)

Now, all of this is separate from STATIC_ROOT, which is a place where all static files are copied when you run ./manage.py collectstatic. For projects just starting out, this is usually in the project root folder: /Users/develop/me/myproject/static/

So we would add, in settings.py:

# /Users/me/develop/myproject/static/
STATIC_ROOT = join(BASE_DIR, 'static')

But this is only really used in production—it's a way to compile all of your static assets into a single spot, and then point /static/ at it with your server (e.g. NGINX).

During development, you can skip collectstatic altogether, and have Django discover and serve your static assets on the fly. Django provides a "serve" view to do this in django.contrib.staticfiles.views.serve.

Try this in your urls.py:

from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
from django.contrib.staticfiles.views import serve


admin.autodiscover()

urlpatterns = [
  url(r'^admin/', include(admin.site.urls)),
]

if settings.DEBUG:
    urlpatterns += [
      url(r'^static/(?P<path>.*)$', serve),
    ]

In your example, you are asking Django to serve files from STATIC_ROOT, which is also fine, but requires you to run ./manage.py collectstatic first, and every time your static assets change—which can be a hassle.

0
votes

In order to serve the static files into your django project you just need to add these lines to your `settings.py

STATIC_URL = '/static/'
STATIC_PATH = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
    STATIC_PATH,
)

and then in the main stucture of your project dictory needs to be like

>Project_dir
>App_dir
>static_dir
>templates
>manage.py

place your css, js, and other static contents into your static_dir