How To Change Django Folder Directory - django

How to change the default static file directory in django. currentyly i'm using this directory:-
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), '..', 'static').replace('\\','/')
I want to change it in my directory in my server for example :-
/var/www/html/uploaded/

Sounds like your real question is how to use different settings in different environments (e.g. a DTAP architecture). There's an ongoing discussion within the django mailing list about settings if you're interested.
You could use a different python file in deployment, e.g.
settings.py
settings_deployment.py
Example of the latter's content
from settings import *
DEBUG = False
MEDIA_ROOT = "/var/www/static/"
Then be sure to load settings_deployment instead of settings on your server.
Another, more dynamic approach would be to overload settings based on an environment setting, its not very hard to fabricate something like that in plain python.

Related

Django deployment variables

I have a development app running locally. I have a production app running on my server. I would like to keep developing locally and push my changes. However, the dev version uses local postgres and the static and media files reside inside the project. The server version the static and media files are in a static public_html directory served by apache. Can I have a local static and media files as well as different postgres credentials on localhost than on the server? How do I accomplish that?
The python-dotenv package is designed specifically for the issue you are running into. Instead of using JSON files it uses .env files which follows the practice of 12 factor apps.
An example would be
settings.py
from dotenv import load_dotenv
load_dotenv()
DEBUG = os.getenv('DEBUG', 1) # with a default value
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
DB_USERNAME = os.getenv('DB_USERNAME')
DB_PASSWORD = os.getenv('DB_PASSWORD')
LOGGING_FOLDER = os.getenv('LOGGING_FOLDER')
# Allowed hosts can be stored and split into a list
# Also the name in the separate settings file does not have to match the settings.py variable name
ALLOWED_HOSTS = os.getenv('HOSTS', '').split(' ')
# This will be ['locahost', 'localhost:8000']
# ...
.env
DJANGO_SECRET_KEY=somethingotherthanthis
DB_USERNAME=postgres
DB_PASSWORD=123456
LOGGING_FOLDER=/var/logging/app/
HOSTS=localhost localhost:8000
Of course you don't have to use the external package you can always use the JSON file and only change the following code in your settings. What you will want to be careful of in both circumstances is that the file you are saving your sensitive data and environment specific information (like media folders, logging folders, etc) is not checked into the version control system.
settings.py
import json
with open('settings.json') as fh:
file_settings = json.load(fh)
DEBUG = file_settings.get('DEBUG', 1)
# ...

Using Django static() to generate audio files' URLs in production

I'm trying to get my Django app to play audio files (supposedly) uploaded by users via a form. Said files are tied to a model :
# models.py
class Doc(models.Model):
# ...
tape = models.FileField()
The uploading and saving parts are working fine, and the files are stored where they should be :
- djangoproject
|
- docapp
|
- media <- here
So, in order to get where I want, I added these two lines to the settings.py file MEDIA_ROOT = os.path.join(BASE_DIR, 'docapp/media/') and MEDIA_URL = 'docapp/media/'.
I hoped to be able to link to the audio files thus:
# templates/docapp/index.html
...
<audio src='{{ doc.tape.url }}' controls></audio>
Unfortunately, this wasn't working because the link generated by doc.tap.url (http://localhost/docapp/media/filename.aac) was returning a 404 error.
After a lot of googling I found this answer, which I happily copy-pasted into my app ... and it worked. This is the code in question :
# urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The problem is that I'm not comfortable with inserting code in my apps that I don't understand. I did some research about the static() function and all I could get is this :
Helper function to return a URL pattern for serving files in debug mode
Does this mean that the static function should not be used in production? If so, what should I be using in production? And what exactly does it do?
EDIT To be clear, the generated URL after injecting the solution is the same as the one generated without it. Yet, it only works when the static() function is present.
EDIT 2 I forgot to mention that the 404 errors persisted even after I chmoded the media folder to allow others to read-access it.
Thanks in advance!
You shouldn't do anything. No errors no problem. The docs write about development server and serving static files AND that it is for development only. In a production environment you configure your server (Apache, NGNIX or third party like S3) to serve the files. That's all.
Try to configure media files and access the file via it's url. If it works, try the {{ doc.tape.url }} template tag.
In your development environment your media may live in /media/ (route and directory). While on production it may be something like media.example.com. Running Django with the settings for that environment will change all static/media domains and paths to their correct locations.
You may split settings file into a settings file for each environment (production, acceptance, development). Like this:
project/
settings/
__init__.py
base.py
local.py
staging.py
test.py
production.py
You can run your project with a specific env: ./manage.py runserver --settings=project.settings.development. Do not repeat yourself and put development specific settings in development.py and from base import * so that base.py contains the default settings.
This project and settings layout is taken from the book Two Scoops of Django. It is just an example. Adjust to your own needs.
Yes, django.conf.urls.static.static is only for development and not for production. For production, you should just need to configure your MEDIA_URL and MEDIA_ROOT settings and have your webserver serve the MEDIA_ROOT directory in the MEDIA_URL path.
Basically adding that in the URL urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) will make the media files in the URL existing. Try removing that and visit your media file in the URL and you will receive a 404 not found. It's very similar to the concept that you are inserting a view for rendering the media files

Django, boto, S3 and easy_thumbnails not working in production environment

I'm using Django, django-storages with S3 (boto) in combination with easy-thumbnails. On my local machine, everything works as expected: if the thumbnail doesn't exists, it gets created and upload to S3 and saves in the easy-thumbnails database tables. But the problem is, when I push the code to my production server, it doesn't work, easy-thumbnails output an empty image SRC.
What I already noticed is that when I create the thumbnails on my local machine, the easy-thumbnail path uses backward slashes and my Linux server needs forwards slashes. If I change the slashes in the database, the thumbnails are showed on my Linux machine, but it is still not able to generate thumbnails on the Linux (production) machine.
The simple django-storages test fails:
>>> import django
>>> from django.core.files.storage import default_storage
>>> file = default_storage.open('storage_test', 'w')
Output:
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_FILE_STORAGE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
If I do:
>>> from base.settings import staging
>>> from django.conf import settings
>>> settings.configure(staging)
This works (I have a settings directory with 4 settings files: base.py, staging.py, development.py and production.py)
It seems that on my production server, the config file isn't loaded properly (however the rest of the website works fine). If I add THUMBNAIL_DEBUG = True to my settings file, but easy-thumbnails' debugging still doesn't work (it does work on my local machine).
What can be te problem? I've been debugging for 10+ hours already.
Try refactoring your settings to use a more object-oriented structure. A good example is outlined by [David Cramer from Disqus:
http://justcramer.com/2011/01/13/settings-in-django/
You'll put any server-specific settings in a local_settings.py file, and you can store a stripped-down version as example_local_settings.py within your repository.
You can still use separate settings files if you have a lot of settings specific to a staging or review server, but you wouldn't want to store complete database credentials in a code repo, so you'll have to customize the local_settings.py anyways. You can define which settings to include by adding imports at the top of local_settings.py:
from project.conf.settings.dev import *
Then, you can set your DJANGO_SETTINGS_MODULE to always point to the same place. This would be instead of calling settings.configure() as outlined in the Django docs:
https://docs.djangoproject.com/en/dev/topics/settings/#either-configure-or-django-settings-module-is-required
And that way, you know that your settings on your production server will definitely be imported, since local_settings.py is always imported.
first try to use:
python manage.py shell --settings=settings/staging
to load shell with correct settings file and then try to debug
For some reason, S3 and easy thumbnails in the templating language didn't seem to get along with each other ... some path problem which probably could be solved at some point.
My solution (read: workaround) was to move the thumbnail generation into the model inside the image field itseld, for example:
avatar = ThumbnailerImageField(upload_to = avatar_file_name, resize_source=dict(size=(125, 125), crop="smart"), blank = True)
For the sake of completeness:
def avatar_file_name(instance, filename):
path = "%s/avatar.%s" % (str(instance.user.username), filename.split('.')[1])
if os.path.exists(settings.MEDIA_ROOT + path):
os.remove(settings.MEDIA_ROOT + path)
return path

deploying django site (wsgi)

Trying to use 2 different settings file for production and dev.
I set DJANGO_SETTINGS_MODULE='mysite.settings_production'
Works perfectly when running server with runserver
When I run it with apache though, apache doesn't seem to use the setting in the ~/.bash_profile and instead use os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") in the wsgi.py file
I guess it's maybe because apache is running on different user , not mine..
ok.. so it seems it's running as www-data on my ec2 ubuntu.
So I have to create the /home/www-data/.bash_profile and set the env variable?
It seems like so much hassle to use a different settings file.
Is there an obviously easier way to do this?
(I don't want to change the wsgi.py file, because it's source controlled)
Using bash_profile is completely the wrong way to do this.
The correct way is to use the wsgi.py file. However, since you don't want to do this (although I don't understand what it being version-controlled has to do with anything) then you can set environment variables directly in your Apache configuration using SetEnv:
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
Well, it's really wrong way. Common method to have separate settings for different environment is to store environment-dependent in local_settings.py (or whatever you name it) and imprort from settings.py
from local_settings.py import *
don't put local_settings.py under project repository as you will override it with each commit. If you want to keep a sample of local settings, put into a separate file, e.g. local_settings.py.example
You can import local settings at the beginning of settings.py (so settings.py settings would override local settings), or at the end, or have two local settings files for both cases.

Django Static Files Development

This seems to be a source of much confusion judging by the amount of similar titles on the subject, however trying everything I could find on static files with the django development server I've almost given up hope!
So my static files are served from C:/Users/Dan/seminarWebsite/static/, in which I have sub folders for images, css etc.
SETTINGS:
STATIC_ROOT = 'C:/Users/Dan/seminarWebsite/static/'
STATIC_URL = '/static/'
The static files app is also active.
URLS:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
TEMPLATE:
"{{ STATIC_URL }}images/vision.jpeg"
However only a broken link appears and at this address: http://127.0.0.1:8000/homepage/images/vision.jpeg and I don't think it should be at that address (homepage is the url name of the page the static image file is being called to).
Based on what you've posted so far, it looks like you're following the docs for django.contrib.staticfiles. I agree that the docs can be difficult to follow especially if one is new to django.
I believe the confusion stems from the fact that django.contrib.staticfiles has two modes of operation:
During the development phase where the development server is used, it dynamically searches for static files in predefined directories and make it available on STATIC_URL
For deployment, it assists in collating static files to a single directory (defined using STATIC_ROOT) so that the static files can be hosted using a webserver suited for static files. This collation is done using python ./manage.py collectstatic.
Here's a quick summary of how to get up and running. I haven't had a chance to try it out so there may be mistakes. Hopefully this will help you get started and at the very least help you understand the docs. When in doubt, do refer to the docs.
Hosting static files on the development server
Make sure you have 'django.contrib.staticfiles' in INSTALLED_APPS
Specify STATIC_URL. This will be the path where your static files will be hosted on.
STATIC_URL = '/static/'
Make sure your files are in the correct directories. By default, staticfiles will look for files within the static/ directory of each installed app, as well as in directories defined in STATICFILES_DIRS. (This behaviour depends on backends listed in STATICFILES_FINDERS).
In your case, you'd probably want to specify your directory in STATICFILES_DIRS:
STATICFILES_DIRS = (
'C:/Users/Dan/seminarWebsite/static/',
)
Make the view accessible by adding the following to the end of urls.py:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
Make sure you have DEBUG = True in settings.py.
That's it.
If you run your dev server (./manage.py runserver), you should be able to access your file via http://localhost:8000/static/images/vision.jpeg (which serves C:/Users/Dan/seminarWebsite/static/images/vision/jpeg).
Linking to static files in your templates
There are two ways to get a correct link for your static files - using the staticfiles template tag, and making STATIC_URL accessible to your templates. Since you've attempted the latter, we'll stick to that.
Make sure you have 'django.core.context_processors.static' in TEMPLATE_CONTEXT_PROCESSORS. If you haven't redefined TEMPLATE_CONTEXT_PROCESSORS then there is nothing to do since it should be there by default.
Make sure you use RequestContext when rendering your template. Example:
from django.template import RequestContext
# ...
def some_view(request):
# ...
return render_to_response('my_template.html', {
"foo" : "bar", # other context
}, context_instance = RequestContext(request))
You should now be able to use the following in your my_template.html:
<a href="{{ STATIC_URL }}images/vision.jpeg" />
Hosting static files on production server.
If all the static files you need to serve are store in that one directory (C:/Users/Dan/seminarWebsite/static), then you're almost there. Simple configure your webserver to host that directory on /static/ (or whatever you set STATIC_URL to) and you're good to go.
If you have files scattered in different directories and/or app specific static files, then you'll need to collate them.
Set STATIC_ROOT to the directory where you want to store the collated files.
Run ./manage.py collectstatic to do the collation.
Configure your webserver to host the that directory (STATIC_ROOT) on /static/ (or whatever you set STATIC_URL to).