Django: Unable to import models globally - django

I am running some python scripts which pertains with a django application.
So I manually made a folder (named scripts) that contains some python scripts but is not made using ./manage.py startapp scripts. Along with this folder there is a modelsapp django app (which contains my models) and then project folder containing settings.py and urls.py.
I run ./manage.py shell < scripts/script.py to run my script.
Now here is a sample code of my scripts.py
from modelsapp.models import *
print(Room.objects.all())
This works pretty well. Now consider a second case. I now just run ./manage.py shell and then put the following commands-
>>>from modelsapp.models import *
>>>def init():
... print(Room.objects.all())
...
>>>init()
This also works pretty well. But now when I run the above code through the file in the first case, it says NameError: name 'Room' is not defined
It looks like the model classes which I just imported aren't accessibly inside a function.
This behavior is a bit weird.
Please help. In case I missed anything to mention, do comment below.
Edit: Since this is a bit weird behavior and am not able to find any answers to it, I am just going to pass the class Room directly to the function init() as a parameter to get the work done as of now.

after you run the django shell, you can run your script with:
>>>execfile('filename.py')
if you want to run it in a normal python shell (not using python manage.py shell) you have to do:
import django
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project(name.settings")
django.setup()

Related

Python 2.7 : Import a module situated in a subdirectory from a different subdirectory

Here's my code configuration:
__init__py
./module_1/foo.py
./module_1/__init__.py
./module_2/bar.py
./module_2/__init__.py
My goal is to be able to import the foo module from bar.py, but I'm getting quite confused on how to do it.
Something such as:
from ..module_1.foo import *
Will raise the following error:
ValueError: Attempted relative import in non-package
EDIT:
Ideally I'd like to be able to run my script in the following fashion:
python ./module1/foo.py
You haven't shown how you are invoking the script, but you need to ensure that your scripts are actually packages in your python path. That's basically what the error message is telling you, you were trying to import a "non-package". You probably don't have your top-level in the python path. For example ...
If your top-level module is called app and your configuration is
<path-to-app>/app/__init__py
<path-to-app>/app/module_1/foo.py
<path-to-app>/app/module_1/__init__.py
<path-to-app>/app/module_2/bar.py
<path-to-app>/app/module_2/__init__.py
You can run your script as follows.
cd <path-to-app>
PYTHONPATH=$PWD python -m app.module_2.bar
Works for me.

Inside Django tests folder not able to import outer modules

I am trying to create a tests folder in my django app.
My app has following structure:
myapp
myapp/tests/__init__
mtapp/tests/test_email
myapp/function
Now i am trying to import function inside test_email file.
and executing test case as
python manage.py test myapp
but this gives me error No module named function.
Please let me know the reason behind this.
First Edit: if i put "import ..function" then its working fine. but is it a right way to do it.
Note: I am using python version 2.7,
Django version 1.5.5
It might be a case of some Cyclic import when you are using from ...filename import function.
It can be resolved by importing the function locally in the TestCase.

(Django) Create a management command that will override the default settings in BaseCommand

We always run our tests off of settings_test, like so: ./manage.py test someapp --settings=settings_test. The problem is that it's sometimes problematic to remember to add the option.
I'd like to introduce a common app that just has the management command test.py. Depending on it's placement in the INSTALLED_APPS setting, it will override the default. Inside the command itself, I'd like to change the default of the --settings option. How can I do that?
I am aware that I can create a local.py file that is similar to manage.py but with settings_test instead of settings. However, the point is to still run ./manage.py, but with having settings_test as default instead of constantly typing "--settings=settings_test" after ./manage.py test someapp
After several attempts, I found that manage.py sets the settings long enough before the actual management command gets called that it's basically impossible (as far as I can tell) to change them there.
Eventually I decided that, since it's seems to be OK to alter manage.py - there's your default settings file there, for instance - that would be a reasonable place to deal with this, so I implemented it there:
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
argv = sys.argv
try:
if argv[1] == 'test' and not any([k.startswith('--settings') for k in argv]):
os.environ["DJANGO_SETTINGS_MODULE"] = "myapp.test_settings"
except IndexError:
pass
from django.core.management import execute_from_command_line
execute_from_command_line(argv)
This seems to work as expected and I don't see any major disadvantage or problem - happy to be corrected.
You can override default commands by implemeting them in your app (say: common_app).
Create a management.commands package in common_app.
And implement a test command in there:
# this is commonapp/management/commands/test.py
try:
from south.management.commands import test
except ImportError:
from django.core.management.commands import test
class Command(test.Command):
def handle(self, *args, **kwargs):
kwargs['settings'] = kwargs.get('settings', 'common_app.settings')
super(Command, self).handle(*args, **kwargs)
This will use the settings.py file in common_app if there's no '--settings=' flag in given. But you can change that string in "settings_test" and it will load the first settings_test.py it can find on your python path.
South does this command overriding too, so for completeness I added the south import. But if any of your other installed apps also override the test command... you get the idea.
Don't forget the empty __init__.py files to make 'management' and 'commands' packages.
RTFM for more info on Django custom management commands.
You can override a django command as #Chris Wesseling describe in his answer.
Note: if there are other apps that are extending the command, move your app above those apps in the INSTALLED_APPS list, i.e.
to override runserver command and you are using 'django.contrib.staticfiles', place your app before staticfiles app
to override test command and you are using a test app i.e. django_nose, the same, place your app before django_nose app

Django tables-import error

i am having an import error django_tables.
Could not import ikapp.views.admin. Error was: No module named django_tables.
It looks like ikapp.views.admin requires django-tables. Unfortunately it's not possible to tell which version/fork it requires, but it's likely to be either:
https://github.com/miracle2k/django-tables
https://github.com/bradleyayers/django-tables2
django_tables requires that you actually be running within the django-"primed" python environment. You can access this by going to your project's directory and typing
python manage.py shell
Then you can import django_tables with no problems.
For further info, take a look at the following: https://docs.djangoproject.com/en/dev/ref/django-admin/

How do I preload imports into Django's manage.py shell command?

When I run manage.py shell on my Django project to take a peek at something there are common imports that I always want to run at the start of the shell (e.g. I always want to import my model files.) How can I have these run automatically everytime I run the shell command?
2nd related question, when I hit the up arrow I get the "^A" character instead of the previously run command in the manage.py shell (and in my regular python shell), how can I fix this so it loads the previous command like on the Linux/Unix command line?
For the first question, look at the manage.py shell_plus command provided by the django-extensions project. It will load all your model files on shell startup. The project has got a whole load of other useful tricks too, so it's definitely worth checking out.
For the second question, I can only guess that you need to install readline.
you can replicate what
python manage.py shell
does by just doing:
from django.core.management import setup_environ
from mysite import settings
setup_environ(settings)
and you will have the environment all set up for the rest of that script. There are some other ways to do this here too: http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/
One single thing which can solve both of your problem is ipython. ipython stores the previous executions and it can give you completion as well.
Auto importing frequently used packages in python manage.py shell_plus
Example:
# local_settings
SHELL_PLUS_PRE_IMPORTS = (
('<app_name>.models', '*'),
('<app_name>.forms', '*'),
('<app_name>.views', '*'),
('django.core.urlresolvers', '*'),
('django.db', 'connection'),
('django.db', 'reset_queries'),
)
SHELL_PLUS_DONT_LOAD = ['<app_name>', '<app_name>']
Reference:
https://github.com/django-extensions/django-extensions/blob/master/docs/shell_plus.rst
Adding extra stuff to the django shell can be done using as a starting point the shell_plus command provided in the django-extesions app, and modifying it by adding whatever you want to make available to the 'imported_objects' dictionary.
Eg if you duplicate the shell_plus.py file and add these two lines at the end:
# .......
alist = range(1000)
imported_objects['alist'] = alist
code.interact(local=imported_objects) # <-- this is the original final line
When you run the shell using the new file the 'alist' reference will be available.
I put a longer example here: http://www.michelepasin.org/techblog/?p=1012