I am trying to execute an external snippet for debugging and terminal-like purposes in the environment the Django console uses so it can connect to the db, etc.
Basically, I am just using it for the same reason one would fiddle with the console but I am using longer snippets to output some formatted information so it is handy to have that code in an actual file manipulated with an IDE.
An answer said you could do that by executing python manage.py shell < snippet.py but I did not see a successfull result. And although no errors are reported, I am not getting the excepted output, but only a series of >>> prompts.
So how can I do this?
By the way, I am using PyCharm, in case this IDE has a shorthand way of doing this or any special tool.
I would say creating a new Custom management command is the best way to achieve this goal.
But you can run your script in a django environment. I use this sometimes to run a oneoff script or some simple tests.
You have to set the environment variable DJANGO_SETTINGS_MODULE to your settings module and then you have to call django.setup()
I copied these lines from the manage.py script, you have to set the correct settings module!
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings.local")
django.setup()
Here is a simple template script which I use sometimes:
# -*- coding: utf-8 -*-
import os
import django
# you have to set the correct path to you settings module
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings.local")
django.setup()
from project.apps.bla.models import MyModel
def run():
# do the work
m = MyModel.objects.get(pk=1)
if __name__ == '__main__':
run()
It is important to note that all project imports must be placed after calling django.setup().
Many times you need scripts to play with db or more. But you need to the the django way i.e. the ORM and play with every thing that your project has.
You can checkout https://github.com/django-extensions/django-extensions
You create a scripts folder in your project home and write down a method run . the app provide you a way to run those scripts easily.
How to do it.
Step 1 - Install the package.
Step 2 - Create a scripts folder with init.py in project root, and add 'django_extensions' in your applications
Step 3- Create a file send_email_to_users.py in scripts folder. Simple Example.
from project.models import MyModel
from django.contrib.auth.models import User
from project.utils import send_email
def run():
results = MyModel.objects.all()
for res in results:
send_mail(res.email)
Now from command line you can run
python manage.py runscript send_mail_to_users
If its just a one off script,
import django
django.setup()
from myapp.models.import MyModel
You need to have your environmental variable set up, so its easiest to run it from the IDE (make it part of the same project, right click on teh file and there should be a run option).
If you are looking for something to run on a production environment I would create a management command as suggested by DanEEStar.
Related
How do I enter the Django Shell? I am not seeing clear instructions on how to achieve this.
You can run that code interactively in the dev shell.
python manage.py shell
For future reference, though: all you need to do to make a plain .py file "Django compatible" is that you set the DJANGO_SETTINGS_MODULE environment variable before importing any Django stuff:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproj.settings")
from myapp.models import Stuff
# ...
I'm try to populate data into my db and I'd like to use the django API to do so. I've written a python module that allows me to this very easily.
However, within the django shell (manage.py), it doesn't seem possible to run my "populate.py" file.
Is it possible to run my populate.py from the django shell? Or alternatively, should I instead be running a regular python terminal and importing the necessary django components? Either way, I would greatly appreciate some pointers.
You can also consider using the loaddata command or create your own command
Here is my standard wrapper for running django stuff from the command line. This is also useful if you have cron scripts you want to run.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
# If this script lives in a child directory of the main project directory
# uncomment the following 2 lines:
#dir_parent = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
#sys.path.insert(0, dir_parent)
from django.core.management import setup_environ
import settings
setup_environ(settings)
from django.db import transaction
# import whatever you like from app.models or whatever
# do random stuff.
# If you are *changing* database records,
# wrap your database code either in:
#transaction.commit_manually
def foo():
... stuff
transaction.commit()
# OR end you script with:
transaction.commit_unless_managed()
Update for comment:
The variable mentioned above is not file, it is __file__ (i.e. 2 underscores file and 2 more underscores). This is always set by the Python interpreter to the full path of the file it occurs in. As the comment says, if this script lives in a child directory of the main directory, the directory-of-the-directory of the filename gives you the directory name of the main project directory, and adding that to sys.path will make sure that all of your imports work correctly. If the script lives in the main directory and you execute it from there, then you don't need to do that.
Try django-extensions it has a runscript command you put in a scripts directory.
Oddly the command seems to be missing from the main documentation but if you google django-extensions runscript you will find examples and documentation.
I have a settings.py file and a dev_settings.py file that I use to override some values for dev purposes. Everytime I run the ./manage.py command, I have to specify --settings=whatever.local_settings. This becomes very tedious to do every time and I am trying to find a way to force manage.py to load my dev_settings.py file every by default so that I don't have to type that long argument every time I want to run a command.
I have tried setting DJANGO_SETTINGS_MODULE, however, it appears that manage.py overrides this option.
Is it possible to make this happen or am I doomed to always specify that argument?
manage.py sets path to settings for you, that's why it's ignoring DJANGO_SETTINGS_MODULE (it's basically just script that wraps around django-admin.py).
There are 2 easy ways to fix your problem:
set DJANGO_SETTINGS_MODULE and use django-admin.py to run all commands instead of manage.py. This is even better if you use vitualenv.
copy manage.py and name it local.py (that's the name in my case) and rename all settings mentions to dev_settings.
For example:
#!/usr/bin/env python
from django.core.management import execute_manager
import imp
try:
import settings_local
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings_local.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings_local)
You can run all commands by ./local.py now.
The way this is typically done is you have settings.py with all settings that are common between environments (things like INSTALLED_APPS, etc.). Then, you have something like settings_local.py, that defines settings particular to the environment in context. You then import settings_local.py in settings.py.
# settings.py
from settings_local import *
settings.py gets added to your source code repository, but settings_local.py does not. (However, you would normally add something like settings_local.py.example to the repo.)
When you first move your app over to production, for example, you pull down the code base from your repo. You then copy settings_local.py.example to settings_local.py and make any necessary environment specific changes.
You then have separate settings_local.py files in each environment, and it all just works.
You can make a bash alias by adding these lines to your .bash_profile file:
mymanage()
{
python manage.py $1 --settings=settings_debug
}
alias mng=mymanage
Then when you run this command:
mng runserver
settings_debug.py file will be used for settings.
You can use django-admin.py with that environment variable. Commands are interchangeable, only django-admin.py doesn't override the variable you're trying to use.
If a settings file is common to all installation, you can just import it e.g.
from settings_local import *
but usually settings_local are changed and tweaked per installation and as my installation script directly copy files to target sites (without worrying what is local what is not), which mean settings_local may get overwritten, to avoid that I just keep settings_local in parent folder of the installation target and manually import it in settings.py e.g.
local_settings_file = os.path.join(prevFolder, "settings_local.py")
if os.path.exists(local_settings_file):
execfile(local_settings_file)
I have problems with importing correctly a module on appengine. My app generally uses django with app-engine-patch, but this part is task queues using only the webapp framework.
I need to import django settings for the app to work properly.
My script starts with:
import os
import sys
sys.path.append('common/')
# Force Django to reload its settings.
from django.conf import settings
settings._target = None
# Must set this env var before importing any part of Django
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
I always get this error, or something related:
<type 'exceptions.ImportError'>: No module named ragendja.settings_pre
because the settings.py file starts with
from ragendja.settings_pre import *
I think I need to add ragendja to sys.path again but I had several tries that didn't work.
Here is my directory:
project/
app.yaml
setting.py
common/
appenginepatch/
ragendja/
setting_pre.py
myapp/
script.py
Is it only a sys.path problem and how do I need to modify it with the correct syntax?
Thanks
App engine patch manipulates sys.path internally. Background tasks bypass that code, so your path will not be ready for Django calls. You have two choices:
Fix the paths manually. The app engine documentation (see the sub-section called "Handling import path manipulation") suggests factoring the path manipulation code into a module that can be imported by your task script.
Eliminate dependencies on django code, if possible. If you can write your task to be pure python and/or google api calls, you're good to go. In your case, this might mean refactoring your settings code.
Why not:
sys.path.append('common/appenginepatch')
since the ragendja is in this directory?
Every time I log on to my server through SSH I need to type the following:
export DJANGO_SETTINGS_MODULE=settings
if I do not any usage of the manage.py module fails
My manage.py has the following added code:
if "notification" in settings.INSTALLED_APPS:
from notification import models as notification
def create_notice_types(app, created_models, verbosity, **kwargs):
notification.create_notice_type("friends_invite", _("Invitation Received"), _("you have received an invitation"))
notification.create_notice_type("friends_accept", _("Acceptance Received"), _("an invitation you sent has been accepted"))
signals.post_syncdb.connect(create_notice_types, sender=notification)
else:
print "Skipping creation of NoticeTypes as notification app not found"
Any ideas?
Yourmanage.py is referencing an application (notifications). This forces Django to complain about DJANGO_SETTINGS_MODULE being set because the Django environment hasn't been set up yet.
Incidentally, you can force the enviroment setup manually, but honestly I wouldn't do this in manage.py. That's not really a good practice in my opinion.
Here is how you can manually setup the Django environment from within any app (or program for that matter):
# set up the environment using the settings module
from django.core.management import setup_environ
from myapp import settings
setup_environ(settings)
You need to set the DJANGO_SETTINGS_MODULE environment variable because it's how Django knows what your settings module is called (so you can have different ones per project or for testing and development.) You can set it in the scripts themselves before you import django (directly or indirectly) but that won't do much good when you run the Django-provided scripts.
The easiest solution is probably to just set DJANGO_SETTINGS_MODULE in your shell's startup scripts, so you won't have to set it manually anymore. The usual files to add it to are .bash_profile and .bashrc (if you do indeed use bash.)
By default, manage.py looks for a settings module in the same directory as itself. If it doesn't find one, it bombs out with a message to use django-admin.py instead. It doesn't actually set up the environemnt until it runs execute_manager. If you need to run your hooks before calling your management functions, the practice I've seen suggested is to put them in the relevant app's models.py.