20

I'm new to Django and want to use its ORM in my scripts without running whole Django thing. I'm scratching my head how to configure it. Searches on StackOverflow didn't help as answers don't show the full picture.

Therefore, I created a small project:

app.py
manage.py
orm/
  __init__.py
  models.py

manage.py has configuration:

from django.conf import settings    
settings.configure(
    DATABASE_ENGINE = 'mysql',
    DATABASE_NAME = 'db',
    DATABASE_USER = 'admin',
    DATABASE_PASSWORD = '',
    DATABASE_HOST = 'localhost',    
    INSTALLED_APPS = ('orm')
)

models.py:

from django.db import models    
class Label(models.Model):
    name = models.CharField(max_length=50) # required max_length

and finally my main file app.py:

from django.conf import settings    
from django.db import models
from orm.models import *   
\# do database maniupaltions

Though after running app.py I receive an error that: django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

What am I doing wrong?

5
  • 1
    django has management commands that you can run as scripts without running runserver. read more here: docs.djangoproject.com/en/1.11/howto/custom-management-commands Commented Aug 9, 2017 at 16:11
  • Use custom command as @VikashSingh has already mentioned. Another alternative could be stackoverflow.com/a/41826771/5616580 Commented Aug 9, 2017 at 16:32
  • 1
    You're configuring settings in manage.py, but you're running app.py. If you're gonna run app.py that's where you need to configure them. You also need to call django.setup() before using the ORM. Commented Aug 9, 2017 at 18:53
  • @knbk django.setup() - I think that's the part i was missing, i made it working, thanks Commented Aug 10, 2017 at 8:54
  • With Django 4.2.6 in late 2023, the solution from the OP in his own answer below works like a charm. Commented Dec 17, 2023 at 23:29

4 Answers 4

21

So your question is :

I want to use Django's ORM in my scripts without running a complete Django application, how to configure it?

I'll share what I did for a project I am currently working on, using Django 2.0.2.

I suggest you create a file SetupDjangoORM.pywith :

import django
from django.conf import settings

settings.configure(
    DATABASES={
        'default': {
            'ENGINE': '<your_engine>',
            'NAME': '<database_name>',
            'HOST': '<hostname_or_ip>',
            'PORT': '<port>',
            'USER': '<user>',
            'PASSWORD': '<super_secret_password>',   
        }
    },
    INSTALLED_APPS=[
        '<your_app>',
    ]
)
django.setup()

You can find this informations in your settings.py file.

Then, you can import this wherever you need :

from . import SetupDjangoORM

And now you are able to use Django Models (ORM) in your scripts.

Sign up to request clarification or add additional context in comments.

2 Comments

I moved the SetupDjangoORM.py to my well working django folder with the apps inside and ran the script. when I try to call from . import SetupDjangoORM i get error from . import SetupDjangoORM ValueError: Attempted relative import in non-package
Did you add __init__.py file to the folder containing SetupDjangoORM.py ?
10

You can find all the information here

This works for version 3.1 of Django

import django
from django.conf import settings
from myapp import myapp_defaults

settings.configure(default_settings=myapp_defaults, DEBUG=True)
django.setup()

# Now this script or any imported module can use any part of Django it needs.
from myapp import models

Comments

7

Here's an updated version, fix was including django.setup() line and some additional settings and includes:

manage.py

import os
import sys
import django
from django.conf import settings

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

INSTALLED_APPS = [
    'orm',
]

DATABASES = {
    'default': {
        'ENGINE' : 'django.db.backends.mysql',
        'NAME' : 'playground',
        'USER' : 'admin',
        'PASSWORD' : 'pasw',
        'HOST' : 'localhost',
    }
}

settings.configure(
    INSTALLED_APPS = INSTALLED_APPS,
    DATABASES = DATABASES,
)

django.setup()

if __name__ == "__main__":
    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

And app.py:

import manage
from orm.models import Label

if __name__ == '__main__':

    Label.objects.create(name='test')
    print(Label.objects.get(name='test'))

Hope someone will find it useful.

1 Comment

The result is very neat. Thank you very much for raising the question and for your conclusion!
0

You can do it with dorm.

DISCLAIMER: I am the maintainer of the package

After installation pip install dorm-project you simply need to add settings.py to the project root with atleast INSTALLED_APPS and DATABASES values

# <proj-root>/settings.py
from pathlib import Path

BASE_DIR = Path(__file__).parent.resolve()

INSTALLED_APPS = []
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}

Ensure that you call dorm.setup() in your projects endpoints to make sure the ORM is ready to use.

import dorm

if __name__ == "__main__":
    dorm.setup()

With that you can start adding your models to models.py files inside any package (known as apps in django, don't forget to add the package to INSTALLED_APPS in settings.py file) - just like how you would do it in a "full" django project.

# blog/models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)
    body = models.TextField()
# <proj-root>/settings.py
INSTALLED_APPS = ["blog"]

All Django management commands like makemigrations, migrate, shell, test, etc can be run using dorm cli

dorm makemigrations
dorm migrate

You can all add unittests that can use the ORM, and run with Django Test Runner:

# blog/tests.py
from django.test import TestCase

from blog.models import Post


class TestPostModel(TestCase):
    def test_creating_object(self):
        post = Post()
        post.title = "Fake title"
        post.slug = "fake-title"
        post.post = "fake body"
        post.save()
dorm test
...
Found 1 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

1 Comment

IMO it's not worth using this package given it just wraps Django and the same things you need to do to use it you can do to use Django directly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.