2

I am a bit of a novice when it comes to Django and Google App Engine, and I've been having trouble setting up project paths in my app settings. Specifically, I'm trying to reference a CSS file for use with a template. My directory structure is as follows:

app/
    app/
        -'__init__'.py
        -settings.py
        -urls.py
        -views.py
        -wsgi.py
img/
static/
    css/
        -style.css
templates/
    -index.html

I think my issue lies in the settings based on the work I've been doing for the past few hours. I started being unable to reference a template, though I figured out how to do that, and let me explain how:

In settings.py, I have the following pieces of information regarding templates:

PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))

TEMPLATE_DIRS = (
    PROJECT_PATH + '/templates',
)

This turned out to be simple enough. I set a PROJECT_PATH which holds the path for the project, and appended the templates directory. However, I'm still having trouble with doing the same for static files, and this is where I'm kind of lost. With regard to static files, I have the following in settings:

PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))

STATIC_ROOT = ''

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    PROJECT_PATH + '/static',
)

Theoretically these default values should work fine as long as the directory I'm using is named '/static/' but it doesn't work the same way as templates. I've tried quite a few different things to try to get these values to point to the correct directory, but only one time have I actually been successful, and I think that was a combination of using absolute paths i.e 'Users/username/app/static/css/' which don't make sense once I deploy the project because I am not hosting it on my computer. Also I probably had moved the static directory inside the app subfolder, which should also be unnecessary. What is different with the static files compared to the template files? Why can I use the PROJECT_PATH and append '/static' to achieve the same result as with the templates?

Some other useful information from my project:

app/urls.py:

urlpatterns = patterns(
    '',
    url(r'^$', views.index, name='index'),
) + staticfiles_urlpatterns()

and:

templates/index.html:

<html>

    <head>
        {% load staticfiles %}
        <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}" />
    </head>

    <body>
        <!--Some stuff-->
    </body>

</html>

and:

app.yaml:

application: siren-1157
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: main.app
- url: /static
 static_dir: static

libraries:
- name: django
  version: "latest"

EDIT : Based on some feedback from @AlexMartelli I've added application_readable: true to the app.yaml, in this way:

- url: /static
  static_dir: static
  application_readable: true

Some other resources I have used while troubleshooting, with ill effect:

Django -- Can't get static CSS files to load https://docs.djangoproject.com/en/1.4/howto/static-files/#configuring-static-files https://github.com/divio/django-shop/blob/master/example/settings.py

Some other things I've tried:

Change reference technique in index.html:

from

{% static 'css/style.css'}

to

{{ STATIC_URL }}css/style.css

Changed PROJECT_PATH with a variety of different os modules

Changed STATIC_ROOT, STATIC_URL, and STATICFILES_DIRS to various different values, from absolute path ('/Users/username/app/static/') to a relative path using PROJECT_PATH or a derivative

Is anyone able to point me in the right direction with figuring out how to set up directories? I feel like I'm close but it's driving me nuts right now.

Community
  • 1
  • 1
Michael Fourre
  • 3,005
  • 3
  • 15
  • 26
  • 1
    Since you mention app engine, can you please show us your `app.yaml`? If you declare files as static there, they won't be accessible to your app's code unless you add `application_readable: True` to the respective stanza -- see https://cloud.google.com/appengine/docs/python/config/appconfig?hl=en#Python_app_yaml_Static_file_handlers for all details. – Alex Martelli Jan 09 '16 at 05:16
  • Let me check it out @AlexMartelli I'll see if I have an answer to that as well. Could be good to check. – Michael Fourre Jan 09 '16 at 05:18
  • @AlexMartelli I've added the app.yaml to the question – Michael Fourre Jan 09 '16 at 05:21

2 Answers2

5

Given the following snippet from your app.yaml:

handlers:
- url: /.*
  script: main.app
- url: /static
 static_dir: static

as explained at Configuring with app.yaml#Static file handlers, a web client accessing your app will get those static files, but your own application's code will not be able to access them. Change your handlers: to

handlers:
- url: /.*
  script: main.app
- url: /static
  static_dir: static
  application_readable: true

and both web clients and your app's own code will have access to those static files (essentially, two copies of those static files will be uploaded, one to live next to your source code so that your app's code can read them, the other where app engine's optimized servers for static files get them from).

felipsmartins
  • 13,269
  • 4
  • 48
  • 56
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • Great, let me give this a try as well. I actually have edited my question with an update to my app.yaml, and have made that change to my source files. I'll see if this will help out. I've mostly managed to actually solve this problem without adding the application_readable boolean but perhaps with this method it will be cleaner or more efficient. I'll find out. – Michael Fourre Jan 09 '16 at 05:29
  • 1
    @MichaelFourre, not more efficient, since as I say you're getting two copies of the static files. It differs in that it does allow your app's code (and that includes django templating and other functionality) to also access the static files, so that you can, if you want, use django's rich staticfiles functionality for part of your static file handling, that's all. – Alex Martelli Jan 09 '16 at 17:34
  • Good to know, thanks. Somehow it seems like I was able to do that even without changing that setting in the app.yaml but perhaps I'm just misunderstanding the function. Thanks for the tip regardless and for the answer as well. – Michael Fourre Jan 09 '16 at 18:13
  • @MichaelFourre, as long as you just serve static files "plain", *without* any of the added functionality from Django's `staticfiles` functionality (a contrib app I believe unless that's changed in recent Django releases), then you can remove that Django app and all its settings **and** the `application_readable` -- that's what almost all of us do on other, lighter frameworks. BTW, if my answer has helped, feel free to accept it (clic on the checkmark-shaped outline next to it), as per normal stackoverflow etiquette. – Alex Martelli Jan 10 '16 at 18:02
  • Okay good to know, I'll take this into account when I'm discerning what to do next. I do think your answer is helpful but it didn't actually "fix" the problem from my initial question, so I'm not sure yet which one I will use as the accepted answer. I'll mull over it longer and see if I can determine which answer truly is most appropriate to accept. – Michael Fourre Jan 10 '16 at 18:49
1

After some further searching on other StackOverflow posts, I found one which had the following suggestion:

Check if you can navigate directly to the desired css file. For example, if you are running on localhost, try to navigate to localhost:8080/static/css/style.css Were you able to view the file?

Upon doing this, I was in fact able to view the file. Then, coincidentally, by attempting to access index again, I was able to see the CSS and was rewarded with the following Log:

INFO     2016-01-09 04:11:00,856 module.py:794] default: "GET /static/css/style.css HTTP/1.1" 200 2796

What may have happened is that by manually accessing the css file, the browser was forced to reload it and utilize it for displaying the index page.

This is a terrible answer to a probably terrible question, but hopefully someone in the future finds it useful.

Michael Fourre
  • 3,005
  • 3
  • 15
  • 26