Django+WSGI: Use app at subpath without changes - django

I'd like to serve a Django application from a subdirectory (for example http://www.stackoverflow.com/django_app/).
I've set up mod_wsgi to serve the page via
WSGIScriptAlias /django_app PATH_TO_DJANGO/wsgi.py
How can I specify settings like LOGIN_URL, STATIC_URL, MEDIA_URL, etc. so Django respects the relative path?
If set STATIC_URL it to "/static/" it tries to reference resources at http://www.stackoverflow.com/static/ instead of http://www.stackoverflow.com/django_app/static/.
But if I set it to "static" (without a leading slash) it is interpreted relative to any URL which is also wrong. For example, the admin page at
http://www.stackoverflow.com/django_app/admin/
tries to load the files from
http://www.stackoverflow.com/django_app/admin/static/
I haven't found a way to tell Django to use http://www.stackoverflow.com/django_app/static without explicitly hardcoding the prefix /django_app within the settings (which IMHO violates the DRY principle because it is already specified in the mod_wsgi-config).
It also prohibits serving the same project under different URLs without modifying the project, which seems odd.

There is no way for it to be automatic. The URLs in those few variables, and LOGOUT_URL, are not automatically prefixed with the SCRIPT_NAME which is passed in with scripts and which identifies the mount point.

Related

Django - admin_media_prefix access from javascript

In the admin, I would like the admin media url to be accessible from any javascript.
I already have it included in the request context.
But in order to be able to access it from an included javascript,
<script type="text/javascript">
window.__admin_media_prefix__ = "{{ ADMIN_MEDIA_URL }}";
</script>
Do I have to put something like that in a base template or is there a cleaner way to do that ?
Media (static) files are not interpreted by django in any way. On a production site python code might not even have an access to that files, as they are probably served by the frontend webserever. So you have a crazy option: use something like server side includes (SSI) to embed the variable content into choosen media files by somehow parsing the config file.
Better idea would be to have same admin media prefix scheme for every site, flexible per-site config file for your webserver of choice, where admin media files would be served from some known location:
location ^~ /media/ {
root /.../django-$django_ver/contrib/admin/;
}
I can provide a somewhat "evil" solution: since Django 1.4 django.contrib.admin is using django.contrib.staticfiles for everything static. Since Admin's Javascript is using missing-admin-media-prefix if it's not found, we can do a redirect, e.g. in Apache:
RewriteRule ^/missing-admin-media-prefix/(.*)$ /static/admin/$1 [L,R=301]
(if your STATIC_URL is set to /static, of course)
This method is especially nice if you hack around stuff in Admin a lot and also don't want to clutter your templates with global Javascript variable declarations.

What is the best practice for serving static files in Django currently

I've found plenty of advice for how to tackle static files in Django 1.x. Is there a best practices way to go about doing so?
There are may approaches to serving static files in Django, but Django 1.3 introduced a new option to handle them. Basically, you can define specific directories at a project level or at an app level that contain static media. Then via a management command, 'collectstatic', you can copy all of the static files in your project directory to a separate directory (likely external to your project) that is served by your webserver. This solves a lot of complications of the previous approaches.
1) It allows 3rd party apps to easily include static files in a standard way. No more creating symlinks from your webserver directory to locations inside of individual python/django modules.
2) It gives you more control over where your webserver can host its static files. For example, you can define all of your static media inside of you project under version control, but then copy it all to an external location anywhere on the filesystem. This prevents having to point your webserver to a location inside of your project.
3) Is splits out static media that that will never change from static media that is uploaded by a user using something like a FileField. This is good because you likely want to keep site-level static media in version control (to be installed on your dev servers), but user-submitted content will upload to a different directory (unlike versions of django prior to 1.3).
I think this functionality used to be a 3rd party module that was merged into core.
Here are the docs:
https://docs.djangoproject.com/en/dev/howto/static-files/
Basically there are a few new settings.py variables:
STATIC_ROOT - This is a directory on your filesystem that will be served by your webserver. When you run ./manage.py collectstatic, all of the static files from your project and it's apps will be copied into the directory that you specify here.
STATIC_URL - This is the url that you will set to represent what url base your content will be based from. If you set this value to "/static/", then "/static/" will prefix all urls of static media that included. You will also use this variable in your templates. For example, in your template, you could specify something like:
<img src="{{ STATIC_URL }}logo.png">
The STATIC_ROOT settings variable specifies where static files are copied to, but you also need to provide a location of where static files are copied from. This can be done by creating a directory in your individual Django apps called "static//", similar to what you would do for templates within an app. Upon running the collectstatic command, Django will copy all of the static files from all of the "static/" directories in all of your apps to the STATIC_ROOT directory. You can also use the STATICFILES_DIRS settings variable to define project-level directories to copy static media from.
Though there are many ways to serve static media, I think this is a nice api set in place by Django that will help with better integrating 3rd party modules. The fact that this feature is now included in core could give some indication that this approach may have gained some momentum.
Hope this helps,
Joe

Django: Site-Wide URL Prefix

I've built a Django site that will live at the root when it's live. Right now it's functioning perfectly at the IP address. For testing purposes, the client has pointed a proxy url at it, but the url has /folder/path in it, so none of the URL patterns match. I put (/folder/path)? into all the url patterns so they now respond, but all of the links are broken because I'm using the {% url %} tag and while the url patterns will match the optional path, they don't include it in that tag.
Clearly I can just hard-code /folder/path into all of my urls (well, into all of the url includes) until testing is complete, but is there a better way to do this?
You manage this when you deploy your application, by correctly setting the WSGIScriptAlias in your Apache configuration (assuming you're using mod_wsgi, which you should be doing). This is passed on to Django, which then automatically prefixes all URL reverse lookups with the correct value. You shouldn't need to do any manual mucking about with prefixes.
For this purpouse I use URL_PREFIX in settings.py and add it in each include in urls.py. I also add it at the beginning of MEDIA_URL, for all images/css/js links to work. But I would also like to hear about some more tricky solution?
if WSGIScriptAlias doesn't work or you can't set it up for some reason, remember that the include() function in a urlconf adds the prefix to all URLs. you can create an urlconf which includes your current root urlconf and mount it at the prefix, and then point your settings.py file to that urlconf.
Disclaimer: haven't tried this myself, but it should work.

django app with a generic name

Django tutorials everywhere use constant-set application name all around - in urls file, in HTML templates, in views. But if I want to distribute an application and let the user sets it name (i.e. its URL postfix on http://server.com/appname) - how can I do?
I must have some common name setting then in configuration, but how to work it for template files, etc?
The only thing that matters with reference to the URL is the app's urlconf. As long as you do your imports via the app's package, e.g. appname.models, appname.views, etc., all consumers of your app will have to do after installation is add it to their INSTALLED_APPS and include() it in their urlconf. Everything else will be found by Django provided they are in their default locations.

Making static file serve location configurable in Django?

I'm developing with Django on my computer, and the location of all my static files are different than on my host. Is there a way to make this a configurable parameter?
For example, on my computer, I have to include jquery.js in my templates, which is located in /includes/jquery.js, but on my host, it's located at ../static/jquery.js, but I don't want to make all of these changes for every template page.
There are two questions here. The first is how to configure where Django finds static files, and the URL prefixes used when linking to/including static resources. The answer to that question is to use the MEDIA_URL and MEDIA_ROOT settings to control the URL mapping and on-disk path info for static media. See the Django setting reference docs for more info on that task.
Then, your second implicit question is how to maintain different settings for your local development environment and the production deployment. There are many different "recipes" for maintaining multiple parallel configuration environments for Django projects, but I find the simplest method to simply be adding something like this to the bottom of my settings.py:
try:
from settings_local.py import *
except ImportError:
pass
Then, if either system (dev or production) has a file called settings_local.py in the root project directory, configuration options set there will override those made in the main settings.py. I then usually add the local file to the ignore list for my version control, and put machine-dependent or security-sensitive data (like database passwords) into it, while the bulk of the configuration can live in the main version-controlled settings.py.
Well, Django config files are python scripts, so you have a great fidelity in them. For example, you may want to create list of locations for every host, and read them in your configuration files.
See the djangodose article on configuring development and production environments and specifically the fourth comment. The instructions given specifically address your question of keeping all settings in the VCS - But what if I'm changing the file that has this configurable location? I don't want to put it on my ignore list.