How to move migrations files to outside of django project? - python

django-project/
migrations/
app1/
.../
src/
app1/
.../
config/
...
settings.py
how to set the path in MIGRATION_MODULES in settings.py to make generated migration files appear in migrations/app1/ folder?
I have tried
MIGRATION_MODULES = {'app1': '..migrations.app1.db_migrations'}
but got errors.
Is not it a bad practice to move migration files from default location?

To move the migration files outside of your Django project, you can do the following:
Make a new directory outside of your Django project to store the
migrations files. In your Django project's settings.py file, set the
MIGRATION_MODULES setting to a dictionary that maps the app labels
to the new directory that you created. For example:
MIGRATION_MODULES = {
'app_name': 'path.to.migration.module',
}
Move the migrations files for each app to the new directory.
Run the makemigrations and migrate management commands as usual.

Here is how to do it.
In settings.py you are going to add these lines:
import os, sys
# Path to django-project/ from __file__ or settings.py
proj_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
# Path to the migration folder
new_mig_folder = os.path.join(proj_dir, 'migrations/')
# And to add the folder to the path
sys.path.append(new_mig_folder)
# Hurrah when you execute the code it will know to look for files in this folder
# Tell Django where the migration files are if not default location
MIGRATION_MODULES = {
'app1': 'app1.folder', # If in subfolder
'app2': 'app2_mig', # If files directly in migrations/app2_mig/
'app3': 'whatever_you_want_to_call_it',
}

Related

How to have different settings.py locally and in production

I want to have different settings.py for when I run my project locally and in production, because I have a setting in settings.py that forces my project to use https, but django runserver.py can only use http, not https, so I am unable to run my project locally now. Also, I want to have debug=True on my computer, and debug=False in production. So how can I have a different settings.py for my computer and for production?
There are some options, one these to create two settings files:
add the following to the end of your settings.py:
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
BASE_DIR = os.path.dirname(PROJECT_APP_PATH)
DEBUG = False
...
...
##################
# LOCAL SETTINGS #
##################
# Allow any settings to be defined in local_settings.py which should be
# ignored in your version control system allowing for settings to be
# defined per machine.
f = os.path.join(PROJECT_APP_PATH, "local_settings.py")
if os.path.exists(f):
import sys
import imp
module_name = "%s.local_settings" % PROJECT_APP
module = imp.new_module(module_name)
module.__file__ = f
sys.modules[module_name] = module
exec(open(f, "rb").read())
Create local_settings.py and overwrite the desired settings:
#####################
# OVERWRITE SETTINGS #
#####################
DEBUG = True
SECURE_PROXY_SSL_HEADER = None
SECURE_SSL_REDIRECT = False
...
You could have a folder called settings that include different python files for the base settings, the dev settings, the staging settings, the production settings and the test settings.
The base settings could be imported in dev, staging, production and test settings and then, you can set the value of existing variables (e.g. DEBUG) or define new variables.
The tree structure could be:
{your-project-name}/
settings/
base.py
dev.py
staging.py
production.py
test.py
Then you can use them such as:
$ python manage.py runserver --settings={your-project-name}.settings.dev
For the deployment, you could pass the proper settings through env variable (e.g. in case of docker images)

Dynamic TEMPLATE_DIRS

I want to be able to have dynamic directories where templates will reside. Let me explain what I mean. I have an application system wich has such a file structure:
\proj
__init__.py
settings.py
urls.py
...
\system
__init__.py
models.py
views.py
urls.py
\modules
\module_1
__init__.py
models.py
views.py
urls.py
\templates ## Attention
one.html
two.html
\module_2
__init__.py
modules.py
\templates ##
three.html
four.html
...
\module_N
...
As you can see there is a modules folder, which contains "atomic" modules, atomic in a sense that they have all necessary files, including templates in one place. So that module_1 has a template folder with its tempaltes, module_2 has a templates folder and all other modules have their own templates folder. What I want is to be able to refer to these templates folders in my settings.py file, so that when I upload a brand new module to modules folder, I would not have to change this settings.py file. So my question is, how can I dynamically build TEMPLATE_DIRS variable:
TEMPLATE_DIRS = (
## how to implement this???
)
EDIT
I'm considering another approach. First, to convert my modules to dinamic applications like this:
MODULES_DIR = 'system/modules'
for item in os.listdir(MODULES_DIR):
if os.path.isdir(os.path.join(MODULES_DIR, item)):
app_name = 'system.modules.%s' % item
INSTALLED_APPS += (app_name, )
And then to do something to make Django look for templates in all applications' folders. But I'm not sure whether it will work and how can I complete this task.
This is simply app-specific templates, which is already catered for by the APP_DIRS flag in the template settings dict. There shouldn't be any other configuration needed.

Media folder changes in production

I'm developing a Django website and I have a media folder where users can upload some stuff. This folder is in my root folder and when I run the server in local (with the ./manage.py runserver) it works fine and put the files in MyApp/media/
The problem is that I have a production server Apache with the website running via mod_wsgi. The folder of my project is in /var/www/MyApp/ and it is creating my media folder in /var/www/media instead of /var/www/MyApp/media.
In my settings I have
STATIC_URL = 'static/'
MEDIA_URL = 'media/'
And the way I'm creating the path for my uploaded files is this:
def generate_path(self, filename):
url = "media/files/users/%s/%s" % (self.user.username, filename)
return url
Any idea of what in production it is changing the directory?
Thanks in advance
Configure your MEDIA_ROOT:
# Project root is intended to be used when building paths,
# e.g. ``os.path.join(PROJECT_ROOT, 'relative/path')``.
PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__))
# Absolute path to the directory that will hold uploaded files.
#
# For more information on ``MEDIA_ROOT``, visit
# https://docs.djangoproject.com/en/1.8/ref/settings/#media-root
MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'uploads/')
Then, use upload_to to specify path relative to your MEDIA_ROOT.

Get the path of "static" folder in django automatically

I am developing Django (1.6) app. In my app I have to use the static images to be displayed on the HTML pages (like magnifying glass for search box,logo,etc). After little bit of research I came to know that we have to create a folder (say "static") which holds the static images and then I have mention the path in my settings.py like shown below :
`STATIC_URL = '/static/'
STATICFILES_DIRS = (
"C:/Users/Welcome/Desktop/business/static/polls",
"C:/Users/Welcome/Desktop/business/static",
)`
I also added the code shown below in urls.py too after which I could get the images on my HTML pages.
urlpatterns = patterns(''......... ...........) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
My question now is every time I change the directory (current working directory or if I transfer the project to another pc ) I have to update the path in settings.py.
How to not do that ? how to get path of "static" folder automatically when I run my project. Please do help. What I'm missing ?
Normally the static files finder of django will expect that your app itself has a static sub-directory, and you can store everything there.
+ myproj
- manage.py
+ app
- __init__.py
- settings.py
- urls.py
+ static <-- notice the static directory.
+ templates
This is good of course for development where the Django server is the one serving these static files. In production you'll need to collect everything to the location declared in your STATIC_ROOT setting with the collectstatic management command.
This way you won't need to change the location each time you copy your project to a new location or a new computer.
Of course, that once you do that you can drop the STATICFILES_DIRS definition from your settings.py. This setting is used to tell Django that there are other static assets that reside outside of a certain app. If you want to use it anyway then you can define those directories relative to the project itself, i.e.:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static")
)
Your urls.py should then use the staticfiles_urlpatterns like this:
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
For more information see the Django documentation on static files:
https://docs.djangoproject.com/en/1.7/howto/static-files/
I just figured out the solution for my question. First you need to get the current working directory and then for looking out for the folder in that current working directory(where your project is being installed) assign this to variable say path_for_images and then pass it to the STATICFILES_DIR as shown below:
path_for_images = os.getcwd()+"\static"
STATICFILES_DIRS = ( path_for images,) <-- note ,(comma) after `path_for_images`
No need to do any changes for the urls.py and images get loaded. This isn't exact pythonic way but it's surely one of the way.

Django can't find template

I know many people have asked, this question, but despite hardcoding the path to my template directory I can't seem to get Django to find my template.
Here is settings.py
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
#django.template.loaders.eggs.Loader',
)
TEMPLATE_DIRS = (
"/Users/full/path/to/marketing_site/templates",
)
This is the views.py file:
def static (request, feature_page):
# this will get the appropriate feature page template.
template = loader.get_template('features/pricing.html')
c = RequestContext(request,{
})
return HttpResponse(template.render(c))
Inside the main folder is the templates folder and the app folder. I use to put the apps in the same folder as settings.py but it appears django 1.4 has changed the default file structure.
My error is:
TemplateDoesNotExist at /features/pricing
Django tried loading these templates, in this order:
Using loader django.template.loaders.filesystem.Loader:
Using loader django.template.loaders.app_directories.Loader:
/Library/Python/2.7/site-packages/django/contrib/auth/templates/feature_pricing.html (File does not exist)
Update:
My logs for the webpage list the TEMPLATE_DIRS as ().
If I put a print statement on the settings.py page for the TEMPLATE_DIRS I get a printout of the TEMPLATE_DIRS appropriately... so somehow the TEMPLATE_DIRS isn't being used (from what it looks like)
I had added in an extra TEMPLATE_DIR in the settings.py
:(
it's better to set up relative paths for your path variables. You can set it up like so:
import os
PATH_PROJECT = os.path.realpath(os.path.dirname(__file__))
...
...
TEMPLATE_DIRS = (
PATH_PROJECT + '/templates/'
)
Also assuming you are using windows you may want to try:
TEMPLATE_DIRS = (
"C:/Users/full/path/to/marketing_site/templates",
)
I'm betting /Users/full/path/to/marketing_site/templates does not contain a features directory, or /Users/full/path/to/marketing_site/templates/features does not contain a pricing.html file.
Based on your comment, it looks like you're calling loader.get_template('feature_pricing.‌​html'), instead of using 'feature/pricing.html'.
EDIT: I didn't notice this before:
Inside the main folder is the templates folder and the app folder. I use to put the apps in the same folder as settings.py but it appears django 1.4 has changed the default file structure.
That could be causing the issue. Change the directory structure to match the 1.4 Django conventions. You might just recreate the project, copy the relevant settings over into the newly create settings.py, and copy all the files.
Try adding project paths to django.wsgi
import os
import sys
paths = ('path/to/project/',
'path/to/more /included/directories/',
)
for path in paths:
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Categories

Resources