Django paths, developing in windows, deploying on linux - django

I'm developing Django apps on my local windows machine then deploying to a hosted linux server. The format for paths is different between the two and manually replacing before deployment is consuming more time than it should. I could code based on a variable in my settings file and if statements but I was wondering if anyone had best practices for this scenario.

The Django book suggests using os.path.join (and to use slashes instead of backslashes on Windows):
import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
I think this is the best solution as you can easily create relative paths like that. If you have multiple relative paths, a helper function will shorten the code:
def fromRelativePath(*relativeComponents):
return os.path.join(os.path.dirname(__file__), *relativeComponents).replace("\\","/")
If you need absolute paths, you should use an environment variable (with os.environ["MY_APP_PATH"]) in combination with os.path.join.

We have a situation very similar to yours, and we've been using different paths in settings, basing on sys.platform.
Something like this:
import os, sys
DEVELOPMENT_MODE = sys.platform == 'win32'
if DEVELOPMENT_MODE:
HOME_DIR = 'c:\\django-root\\'
else:
HOME_DIR = '/home/django-root/'
It works quite OK - assumed all development is being done on Windows.

Add
import os.path
BASE_PATH = os.path.dirname(__file__)
at the top of your settings file, and then use BASE_PATH everywhere you want to use a path relative to your Django project.
For example:
MEDIA_ROOT = os.path.join(BASE_PATH, 'media')
(You need to use os.path.join(), instead of simply writing something like MEDIA_ROOT = BASE_PATH+'/media', because Unix joins directories using '/', while windows prefers '\')

in your settings.py add the following lines
import os.path
SETTINGS_PATH = os.path.abspath(os.path.dirname(__file__))
head, tail = os.path.split(SETTINGS_PATH)
#add some directories to the path
import sys
sys.path.append(os.path.join(head, "apps"))
#do what you want with SETTINGS_PATH

Related

Flask: render_template with path

I have several different templates that I'm trying to use for my flask app.
I have tried the following but it seems to only look directly inside /templates and not /templates/folder1, templates/folder2 etc.
return render_template('index.html', template_folder='folder1')
return render_template('folder1/index.html')
both do not work as expected, how can I specify the sub folder of different templates.
The template folder can be specified when creating the Flask app (or Blueprint):
from flask import Flask
app = Flask(__name__, template_folder='folder1')
Source: http://flask.pocoo.org/docs/0.12/api/#application-object
from flask import Blueprint
auth_blueprint = Blueprint('auth', __name__, template_folder='folder1')
Source: http://flask.pocoo.org/docs/0.12/blueprints/#templates
The template_folder is relative to where the app/blueprint is located.
Use the os library to create paths to template folders outside of the app/blueprint directory.
eg.
import os
APP_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATE_PATH = os.path.join(APP_PATH, 'templates/')
run from subdirectory of app root
APP_PATH retrieves parent directory path (app root)
Be sure the Python file and Template folder are all under the same working directory folder.
I think Sean is right, but also: have you tried double quotes? I'm using Blueprint, so it may be different, but this is what mine looks like:
return render_template("users/register.html")
so yours may be:
return render_template("folder1/index.html")

Django template location with Cloud9

I'm learning Django and have just moved everything to Cloud9. I don't understand how to point to my templates on Cloud9?
On my local machine I have the template directory set to /home/user/etc/etc/templates and it works fine. I can't seem to grasp what the path should be when putting it in Cloud9?
It's not realy good to use absolute and hardcoded path in your projects, just because you can work on different PCs or environments. So, you can define your project path according to your settings.py file. Place this somewhere in the begining of the settings.py:
import os
PROJECT_DIR = os.path.dirname(os.path.realpath(__file__))
So now you have variable PROJECT_DIR which will point to your Django project location on every PC and every env. And now, you can use it in your project in template dirs or in static files dirs like this:
# Like this
TEMPLATE_DIRS = (
os.path.join(PROJECT_DIR, 'templates'),
)
# Or like this, pointing to one dir UP
TEMPLATE_DIRS += (
os.path.join(PROJECT_DIR, '../templates'),
)
Also, if you settings file containt this rows:
TEMPLATE_LOADERS = (
'django.template.loaders.app_directories.Loader',
)
Your django application will automaticaly look for templates in you applications templates dir. For example
-apps
-main_app
-templates
-blog_app
-templates
You main_app and blog app templates dirs will be detected automaticaly, without adding them to templates_path.

How to give the path for template directory

My templates are not recognized and I'm getting the following error.
os.path.dirname(__file__)+'\\template' NameError: name 'os' is not defined
The code which I have used in settings is:
os.path.dirname(__file__)+'\\template'
what should I do now.
You could see the relevant knowledge in Definitive Guide to Django Page 99:
import os.path
TEMPLATE_DIRS =(os.path.join(os.path.dirname(__file__),'templates').replace('\\','/'),)
Where explains how it works
This example uses the “magic” Python variable file, which is automatically set
to the file name of the Python module in which the code lives. It gets the name of the
directory that contains settings.py (os.path.dirname), joins that with templates in a
cross-platform way (os.path.join), then ensures that everything uses forward slashes
instead of backslashes (in the case of Windows).
Import the module os
import os
os module is missing You have used it without importing
Add this in your settings.py
import os
TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'templates'),)
and place all your templates under templates folder in your project
and you can use absolute paths like linux(/home/your_project/../templates) in windows ("C:/your_project/../templates")
but it is not good practice
2022 answer.
Keep templates folder in the same directory as the manage.py file
#settings.py
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = os.path.join(BASE_DIR,'templates')
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIR],
...

Separate custom settings variable between development, staging and production

I'm following the project structure as laid out by Zachary Voase, but I'm struggling with one specific issue.
I'd very much like to have a custom settings boolean variable (let's call it SEND_LIVE_MAIL) that I would be using in the project. Basically, I'd like to use this settings variable in my code and if SEND_LIVE_MAIL is True actually send out a mail, whereas when it is set to False just print its contents out to the console. The latter would apply to the dev environment and when running unittests.
What would be a good way of implementing this? Currently, depending on the environment, the django server uses dev, staging or prd settings, but for custom settings variables I believe these need to be imported 'literally'. In other words, I'd be using in my views something like
from settings.development import SEND_LIVE_MAIL
which of course isn't what I want. I'd like to be able to do something like:
from settings import SEND_LIVE_MAIL
and depending on the environment, the correct value is assigned to the SEND_LIVE_MAIL variable.
Thanks in advance!
You shouldn't be importing directly from your settings files anyways. Use:
>>> from django.conf import settings
>>> settings.SEND_LIVE_MAIL
True
The simplest solution is to have this at the bottom of your settings file:
try:
from local_settings import *
except ImportError:
pass
And in local_settings.py specify all your environment-specific overrides. I generally don't commit this file to version control.
There are more advanced ways of doing it, where you end up with a default settings file and a per-environment override.
This article by David Cramer covers the various approaches, including both of the ones I've mentioned: http://justcramer.com/2011/01/13/settings-in-django/
import os
PROJECT_PATH = os.path.dirname(__file__)
try:
execfile(os.path.join(PROJECT_PATH, local_settings.py'))
except IOError:
pass
Then you can have your local_settings.py behave as if it was pasted directly into your settings.py:
$ cat local_settings.py
INSTALLED_APPS += ['foo']
You can do something like this for a wide variety of environment based settings, but here's an example for just SEND_LIVE_MAIL.
settings_config.py
import re
import socket
class Config:
def __init__(self):
fqdn = socket.getfqdn()
env = re.search(r'(devhost|stagehost|prodhost)', fqdn)
env = env and env.group(1)
env = env or 'devhost'
if env == 'devhost':
self.SEND_LIVE_MAIL = # whatever
elif env == 'stagehost':
self.SEND_LIVE_MAIL = # whatever
elif env == 'prodhost':
self.SEND_LIVE_MAIL = # whatever
config = Config()
settings.py
from settings_config import config
SEND_LIVE_MAIL = config.SEND_LIVE_MAIL

Why am I getting absolute urls in Satchmo when I upload product images locally?

I'm doing some local development using Django and Satchmo. When I upload product images locally via the admin, the path to the image shows up as an absolute path, complete with drive letter, rather than the proper relative path.
Stranger still, Satchmo saves both the original image and the thumbnails it generates in both me /media/ directory and /media/images/ directory, the latter being where I want them to go.
The relavent settings are as follows:
# path relative to the settings.py file
DIRNAME = os.path.abspath(os.path.dirname(__file__).decode('utf-8'))
MEDIA_ROOT = os.path.join(DIRNAME, 'media')
MEDIA_URL = 'http://localhost:8000/'
ADMIN_MEDIA_PREFIX = '/media/'
I have tripple checked the local_settings.py file and there is no mention of the word 'media' anywhere in it, so I'm sure there are no setting overrides.
If it helps, I'm on Windows, but I'm using all the proper unix notation for my paths.
This is a Windows only bug. I am developing a Satchmo app on Windows and it does this, but when I deploy on a Linux box it works just fine. I just go into the database and edit the paths there when I am doing testing on my Windows box.
Turns out the issue is a problem with slash directions in the settings.py file.
Usually, I create a relative_path() function in my settings.py file so I can easily set:
MEDIA_ROOT = absolute_path('media')
The version of Satchmo I was using encouraged the use of a DIRNAME setting instead:
DIRNAME = os.path.abspath(os.path.dirname(__file__).decode('utf-8')
The issue was, using this technique, my MEDIA_ROOT was being set as such:
MEDIA_ROOT = os.path.join(DIRNAME, 'media')
But this was using the Windows backslashes instead of the Unix forward slashes. I've resolve it with:
MEDIA_ROOT = os.path.join(DIRNAME, 'media').replace('\\', '/')