1

I want a python script that will update a django db. I have one that works fine when it is a top level of the django project directory, but fails with an ImportError when it is in a subdirectory.

Although my project is a more complicated than this, here is a pared down example of my project directory:

    myproj/
    ├── settings.py
    ├── manage.py
    ├── bin/
    ├── myapp/
    │   ├── __init__.py
    │   ├── models.py
    │   ├── templates/
    │   ├── urls.py
    │   ├── views.py
    └── myproj.db

The package myproj is in the python path, and inside settings.py, the INSTALLED_APPS tuple lists 'myapp'.

Now, if I have a simple python script like this

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproj.settings'

from django.contrib.auth.models import User

print User.objects.filter(username='foo').count()

and I name this test.py and put it at the top of myproj/ and then from inside myproj/ run python test.py everything works just fine (e.g. a 1 is printed if I have a user called 'foo').

If I simply move test.py into myproj/bin/ and from inside myproj/bin do python test.py I get a cascade of errors like this

    Traceback (most recent call last):
      File "test.py", line 6, in <module>
        print User.objects.filter(username='foo').count() 
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 155, in filter
        return self.get_query_set().filter(*args, **kwargs)
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 669, in filter
        return self._filter_or_exclude(False, *args, **kwargs)
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 687, in _filter_or_exclude
        clone.query.add_q(Q(*args, **kwargs))
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1271, in add_q
        can_reuse=used_aliases, force_having=force_having)
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1139, in add_filter
        process_extras=process_extras)
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1325, in setup_joins
        field, model, direct, m2m = opts.get_field_by_name(name)
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/options.py", line 351, in get_field_by_name
        cache = self.init_name_map()
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/options.py", line 380, in init_name_map
        for f, model in self.get_all_related_m2m_objects_with_model():
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/options.py", line 469, in get_all_related_m2m_objects_with_model
        cache = self._fill_related_many_to_many_cache()
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/options.py", line 483, in _fill_related_many_to_many_cache
        for klass in get_models(only_installed=False):
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 197, in get_models
        self._populate()
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 72, in _populate
        self.load_app(app_name, True)
      File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 94, in load_app
        app_module = import_module(app_name)
      File "/usr/local/lib/python2.7/dist-packages/django/utils/importlib.py", line 35, in import_module
        __import__(name)
    ImportError: No module named myapp

I'm not sure what to make of these errors. They don't really make it clear what has gone wrong. Presumably django is using its own importing functions and presumably they are being affected by the relative position of the python script and settings.py file.

Any insights?

4

1 回答 1

0

问题是这一行:os.environ['DJANGO_SETTINGS_MODULE'] = 'myproj.settings'

  • 当您的脚本在 outsidemyproj/时,您的 PYTHON_PATH 从 outside 开始myproj/,因此myproj是一个有效的包。

  • 当您的脚本在 insidemyproj/时,您的 PYTHON_PATH 从 inside 开始myproj/,因此myproj不再是有效的包。

解决方法是从脚本内部显式设置 PYTHON_PATH。

然而

你应该做的是将你的脚本变成一个管理命令,这样你就可以运行python manage.py myscript并确保 Django在运行你的代码之前已经完成了所有必要的初始化和检查。

于 2013-10-04T02:47:31.713 回答