Making static file serve location configurable in Django? - 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.

Related

Django Admin wont allow me to allocate permissions to Users or Groups

I am using django 1.8.6 and have a new application created in a virtualenv using python manage.py startproject. I have set up my INSTALLED APPS and my database settings (postgresql) and I have run migrate to create the backend. So far all seems fine. I then created a superuser using the createsuperuser command and that all seemed to go fine too. My admin.py file is in place and the content of which is as follows:
from django.contrib import admin
from django.contrib.admin import AdminSite
from myapp.models import mymodel
Class mymodelAdmin(admin.ModelAdmin):
list_display = {col1, col2, col3}
admin.site.register(mymodel, mymodelAdmin)
All what appears to be fairly simple standard stuff, so far so good.
I'm using apache to render my webpages and having configured my virtualhost stuff I can happily log in to my admin page and see everything I have registered plus the default django admin stuff. I can create a new user with no problem and I can create a new Group with no problem. Where I am running into trouble is I ma not able to assign any standard permissions to with my new user or my group. I can see the list of permissions from my database with no problem but the button that I need to click to move a permission from available to assigned seems to be disabled and I cannot find any information anywhere or in any tutorials or blogs that might help me to unravel this issue. I have been able to replicated this on every installation that I have done following various different tutorials but I still end up with the same problem.
Can anyone please shed any light on what I am missing? Thanks in advance.
UPDATE: So there seems to be an issue with my static files. I have yet to create any static files of my own for the app so the only static files are the ones installed when I use pip to install everything. I'm using a virtual environment (env) inside my project and the structure is as follows:
/var/www/<my project>/env
/manage.py
/<my app>/settings.py
/urls.py
/wsgi.py
/templates
/static
/media
My project static directory is empty as I believe that collectstatic should collect all the static files and put them in here. All the other static files are stored in the site-packages directory within my virtual environment but clearly they are not being accessed. Any help on this would be gratefully received.
Problem Solved...Hoorah! This was a tough one because everything looked fine except for one little thing. Permissions! However the issue wasn't with permissions at all. A red herring I'm afraid. The issue was all to do with static files and trying to get your head around what's going on and making sure you've got your paths all sorted.
For newbies the key is to specify your main static files directory as an empty directory. This is intentional as the collectstatic routine will populate it for you. It seems to me that you should run this routine after you have installed any apps or plugins that you have defined in INSTALLED_APPS. This routine will go off and find all the static files that these apps need to work properly and will copy them to your base static directory. (Make sure you set the permissions to this directory properly otherwise it wont write the new sub-directories etc.) Once copied you will see in your static directory a list of sub directories containing each set of static files separately so as they don't override each other. Follow this theory and all will work fine. By extension when you create your own static files for your applications, you should keep them in a separate static directory located in your folder. Within this you should have another directory named the same as your app and all your static files should be stored in there. Then when you run the collectstatic routine again, it will copy all your static files to the base static directory and store them neatly in your own app's sub directory so as not to conflict with others.
So in essence you have two static folders at the following paths:
/var/www//static (left empty at the same level as manage.py)
/var/www///static/
I have read a lot (and torn a lot of hair out) to get to this point. Somewhere I read someone's post who said that the base static directory (the empty one) is a red herring and you should delete it. I believe this is wrong advice.
Phew! Got there and hope this helps someone else.

Django-cms for multiple websites

How to setup a django-cms project to support multiple websites?
There's no reference to this in the official documentation and only limited information in the mailing list, but it's in the headline "A Django application for managing hierarchical pages of content, possibly in multiple languages and/or on multiple sites." and through the Django Sites Framework there's already built in support, and in the admin pages can be associated to different sites.
Related:
Django-CMS: Multiple domains on same project
there are a few different options to manage different websites (and, thus, templates and page contents) in Django-cms.
The basic approach
My favorite is probably the simplest:
In my virtualenv I have a single django-cms installation AND a single "project" that contains ALL the templates I use.
I have a global settings file plus one for each website that does only import all global settings and set "SITE_ID".
from base import *
SITE_ID = XXX
For structure i usually have a settings folder, an empty __init__.py inside, a base.py with all the common settings - including django-cms settings, and then the different websites eg. site1.py site2.py etc. (sometimes my structure is even slightly more complex to also account for dev/production, different machines, etc. but that's not relevant here).
I launch each website as a different instance - I use gunicorn so that's extremely easy too, each one of a different port.
I have an nginx fronted with a separate server configuration for each of my websites, and each of these points to a different gunicorn.
server {
listen 80;
server_name example1.com www.example1.com;
...
location / {
proxy_pass http://localhost:PORT;
}
}
Any of the gunicorn instances can access the admin, and all the data is shared in a single database, but for simplicity
That's all!
Of course it can be done similarly with Apache, mod_wsgi and different virtualhosts.
Advanced
Themes
I actually structured my folders to have an apps folder called themes. Each theme is actually an APP, though mostly contains only the templates and static folders, and it's added to the INSTALLED_APPS.
This allows for cute things such as inheritance and/or overriding between different themes.
Dynamic SITE_ID
It's also possible to use a middleware that will dynamically extract and set the SITE_ID from the URL. This allows to have one single instance... but I don't see any real advantage in this solution and rather find it a potential source of risks.

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: How to use static files (simple case, jquery)

I am trying to use jQuery on a Django site. I need to include the jQuery.js library. I have read a lot about Django static files, but I don't think anyone has asked this particular question. I have only three static files to serve: jquery.js, anothersmallfile.js, and styles.css. The Django docs on static file serving say:
"For small projects, this isn’t a big deal, because you can just keep the static files somewhere your web server can find it. link
I would like to "just keep them somewhere my webserver can find them" because elsewhere the Django docs clearly state (warn) that their static-files serving method is only for a development environment. I only have a few static files and I just want the simplest secure solution.
Unfortunately I can't get it working. No matter where I put the files, Django can't find them. Debugging through Chrome web developer console I see I'm getting a 404 error:
GET http://127.0.0.1:8000/templates/polls/jquery.js 404 (NOT FOUND)
I am new to running a server. Do I A.) need to tell my urls.py file where to find static files? or perhaps the problem is B.) that I have misunderstood this issue - Django is my webserver (for production) so right now I must use the Django static files solution?
Doesn't seem like it ought to be very difficult to get my templates to simply recognize a .js file that's in the same directory as they are. Am I missing something?
Edit, before I get more downvotes: I am talking about this passage from the page linked above:
///////////////////////
Django developers mostly concern themselves with the dynamic parts of web applications – the views and templates that render anew for each request. But web applications have other parts: the static files (images, CSS, Javascript, etc.) that are needed to render a complete web page.
For small projects, this isn’t a big deal, because you can just keep the static files somewhere your web server can find it. However, in bigger projects – especially those comprised of multiple apps – dealing with the multiple sets of static files provided by each application starts to get tricky.
That’s what django.contrib.staticfiles is for: it collects static files from each of your applications (and any other places you specify) into a single location that can easily be served in production.
///////////////////
Emphasis added
So if that's what django.contrib.staticfiles is for, what's the simpler solution? I dispute that this is a repeat of prior questions.
You need to read that documentation more closely. That warning is for production. In development, you do use that static-serving method, ie putting it in your urls.py. And, that documentation will also show that the templates directory is not the right place to put them: a separate static or media directory is.
Edit after comment I really don't understand your comment. Either you do it in development via the static serving view, or you use your production server. But you say you don't have a production server. When you get one, whether it's Apache or Nginx or whatever, you put your static files in a directory and tell that server to serve files from there. That is the simple solution. The staticfiles app, exactly as in the docs you quoted, are for when you've got lots of files in different apps (and it simplifies the move from development to production, not complicates it as you seem to think).
Suppose your app is www.
setting.py -> STATIC_ROOT = 'static/'
make dir www/static
make file www/static/some.html
in browser localhost:8000/static/some.html
That's all.

How do you setup a Django project with different sites using the same data?

I'm currently looking at the the documentation for Django sites:
http://docs.djangoproject.com/en/dev/ref/contrib/sites/#ref-contrib-sites
which explains how to associate content with multiple sites. The example used is LJWorld.com and Lawrence.com.
What does the Django project structure look like for the above? Is each site an app on its own, for instance:
project/
manage.py
settings.py
urls.py
ljworld/
models.py
views.py
lawrence/
models.py
views.py
If ljworld has SITE_ID=1 and lawrence has SITE_ID=2, does the SITE_ID variable has to be explicitly set in ljworld/settings.py and lawrence/settings.py?
How do you run the dev server of either ljworld or lawrence?
Update:
I used two sites with shared content in the above. What should be done if there are n different sites who are sharing the same content? Do I really need n different Django projects on n different servers, all connected to the same database server?
Moreover, if I need to make a change in settings.py which should affect all those web sites, it will be very tedious to change each of those files manually.
No, each site is not an app on its own; each site is a project on its own. The whole idea is to have different projects with a (fully or partially) shared content. So you might have a structure such as:
ljworld/
manage.py
settings.py
urls.py
ljworld_specific_app1/
...
lawrence/
manage.py
settings.py
urls.py
lawrence_specific_app1/
You would normally use two Web servers to serve the projects - though normally both would refer to the same DB server. Naturally you can also have apps which are shared between the two projects - just keep them somewhere in the server's PYTHONPATH.
Edit:
"Two Web servers" of course doesn't necessarily mean two physically different servers. They could well be two virtual hosts running under the same Web server instance - heck, you could even map the two projects to two different directories under the same virtual host.
For shared settings, you could use the same technique as for shared apps. Have a global_settings module which contains the shared settings available somewhere on the PYTHONPATH and import it from each of the settings.py.
And if you wanted something really hackish, you could probably even drop all the different projects, use just one and create a middleware that changes settings on the fly. But I would advise against it.