Django脚本,无需使用manage.py shell即可访问模型对象


74

我正在编写一个脚本,将一些模型对象导入到我的django应用程序使用的数据库中。过去,我通过运行./manage.py shell然后再解决了这个问题import myscript。我敢肯定有更好的方法。我希望能够使用在HD的任何位置调用脚本python scriptname.py,并且在该脚本的前几行中,它将执行任何必需的导入/其他操作,以便它可以访问模型对象并像运行时一样运行使用manage.py shell

要实现此目的,我需要添加什么内容?

编辑:

基于@Melug的答案,此外还动态设置了Python路径以解决问题的“ HD上的任何地方”:

import sys
sys.path.append('c:\\my_projec_src_folder')
from myproject import settings
from django.core.management import setup_environ
setup_environ(settings)

Answers:


22

您需要先设置django环境:

from your_project import settings
from django.core.management import setup_environ
setup_environ(settings)

最后导入您的模型,一切就像django一样。


29
setup_environ(settings)自Django 1.4起已弃用!我在下面的帖子显示了一个替代示例,包括一个示例。
迈克尔

148

从Django 1.4开始,您应该避免使用setup_environ(settings)(由Melug发表),因为它已被弃用。请改用以下内容,您将可以访问模型

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_project_name.settings")

# your imports, e.g. Django models
from your_project_name.models import Location

# From now onwards start your script..

这是访问和修改模型的示例:

if __name__ == '__main__':    
    # e.g. add a new location
    l = Location()
    l.name = 'Berlin'
    l.save()

    # this is an example to access your model
    locations = Location.objects.all()
    print locations

    # e.g. delete the location
    berlin = Location.objects.filter(name='Berlin')
    print berlin
    berlin.delete()

示例模型:

class Location(models.Model):
    name = models.CharField(max_length=100)

4
仅在导入os之后立即将os.environ.setdefault(“ DJANGO_SETTINGS_MODULE”,“ your_project_name.settings”)移至该行之后,此方法才对我有用。否则,这是一个更好的解决方案。
彼得H

好点,彼得!也许某些模型导入仅os.environ.setdefault(...)在行之后起作用。我在帖子中重新排列了导入内容,现在它应该适合所有人。PS:如果您更喜欢此解决方案,请投票。谢谢!
迈克尔

没有外部设置文件,我可以这样做吗?也就是说,我想在单个脚本中构建模型,连接以及所有内容。我不在乎意见...
isaaclw

@isaaclw我不相信没有设置文件也可以做到这一点。如果您找到方法,请告诉我们。顺便说一句。我settings.py没有处理任何意见,它处理的连接参数,所有视图里面的定义如下调试模式等标志myapp/views.py,并且可以通过URL模式访问定义的urls.py
迈克尔

我几乎拥有它,我只需要将设置文件设置为某种东西即可。目前,我将其设置为空字符串。正确设置了DATABASES = {}。然后:os.environ["DJANGO_SETTINGS_MODULE"] = ''settings.configure(**locals())这一切到来之前from django.db import models
isaaclw

126

为了也加载模型,我必须将此与这个答案结合起来,否则我得到django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
import django
django.setup()

另外,我将其添加到__init__.pydjango项目的中,它会自动发现应用名称,因此可以复制/粘贴:

import os


def setup():
    module = os.path.split(os.path.dirname(__file__))[-1]
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{}.settings".format(module))
    import django
    django.setup()

然后我可以这样做:

from <app> import setup
setup()

8
谢谢,显然自Django 1.7起需要调用setup()。
Phae7rae

1
init中的setup()很好,喜欢它!
ulath '16

1
现在这应该是正确的答案。唯一适合我的解决方案。
编码

我注意到2件事:1)在多个文件中进行设置时会引发错误,2)在models.py中调用setup()无效,否则,答案非常好
yvesva

1
@yvesva您不应该从您的models.py调用它。这是用于从外部脚本初始化django。不要在标准django应用调用流程中使用此功能。并将其放在多个文件中应该没有任何问题吗?只要函数获得的模块路径合适,它就会起作用。我得到的印象是您没有正确执行此操作。
Rebs


38

对于Django 1.9或更高版本,您可以使用以下命令:

import sys
import os
import django

sys.path.append('your_project_directory')
os.environ['DJANGO_SETTINGS_MODULE'] = 'your_project.settings'
django.setup()

from yourapp.models import your_model

因此您可以将对象用作相同的Django对象:

from myapp.models. import Locations
all_locations = Locations.object.all()
first_location = Locations.object.get(id=1)
print first_location.name()
first_location.save()

3
这对我有用!Django 2.0。为什么我们确实需要在项目目录后附加路径?在什么django.setup()上有什么好的信息吗?
timbram '18 -10-16

@timbram-您发现了吗?有没有一种方法可以在诸如Sublime Text 3或Atom的文本编辑器中自动执行此操作?
zerohedge

7

对于DJANGO 1.11

上层解决方案不起作用,但给了我一个错误:

django.core.exceptions.AppRegistryNotReady:应用尚未加载。

对我来说,这里的解决方案:

import os
from django.core.wsgi import get_wsgi_application

os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'
application = get_wsgi_application()

3

从Django 1.11开始,您的主应用程序包含一个wsgi模块,该模块在导入时进行必要的设置。假设myproject/myproject您的settings.py在哪里,在脚本中只需导入:

from myproject.wsgi import application

2

这是Django版本> 1.4的答案:

from django.core.management import settings
from myproject.myproject import settings as project_settings

if not settings.configured:
  settings.configure(default_settings=project_settings)

2

对于Django> = 2.0,足以完成这两次导入

from your_project_path import settings as your_project_settings
from django.core.management import settings

那你就可以做 from my_app.models import MyModel

并使用您的模型 MyModel


1

如果你得到:

django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

尝试:

import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
application = get_wsgi_application()

2
我正在Django中使用独立脚本,该脚本正在导入模型。我尝试了上述技术,但遇到以下错误RuntimeError:populate()未重入
AR7

@ AR7是否找到解决此错误的方法?我遇到了同样的问题。
ZeCarioca,

我认为当您多次调用get_wsgi_application()时会发生reentrat错误。
伊萨扎(Juan Isaza),

1

尝试:

os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings"

如果os.environ.setdefault不起作用。(Windows 10,python3.6.4,django 2.0.3)


0

正如Stavros在这里指出的那样,您只需复制wsgi.py并将其放在脚本的开头即可。除了设置DJANGO_SETTINGS_MODULE,您还需要获取应用程序。希望能帮助到你。它在Django 2.1.5上对我有效。

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'revochem.settings')

application = get_wsgi_application()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.