29

I've used Django ORM for one of my web-app and I'm very much comfortable with it. Now I've a new requirement which needs the database but nothing else that Django offers. I don't want to invest more time in learning another ORM like SQLAlchemy.

I think I can still do:

from django.db import models

and create models, but then without manage.py how would I do migration and syncing?

Dave Mackey
  • 4,306
  • 21
  • 78
  • 136
swapnil jariwala
  • 1,064
  • 2
  • 12
  • 19
  • 2
    Possible duplicate of [Use Django ORM as standalone](http://stackoverflow.com/questions/937742/use-django-orm-as-standalone) – user1797792 Oct 16 '15 at 12:08
  • 3
    Agree, Question is duplicate of "use-django-orm-as-standalone" and "Use only some parts of Django?" and "using-only-the-db-part-of-django" but the answers are for older versions of django, if I close this question, It would take ages for someone to write answer for latest version and to get it to top 1st or 2nd answer. – swapnil jariwala Oct 17 '15 at 03:57
  • Possible duplicate of [Using django for CLI tool](http://stackoverflow.com/questions/32088702/using-django-for-cli-tool) – e4c5 Oct 17 '15 at 04:42

5 Answers5

34

There are a lot of answers out there that work with older versions of Django, but Django is constantly updating and in my research I found no viable answer for Django 1.8/1.9, so I had to roll my own. Here's how you do it:

Project Structure:

├── data
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   └── models.py
├── main.py
├── manage.py
└── settings.py

The data directory and migrations directory contain empty __init__.py files. The sample models.py file reads as follows:

# models.py
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField(max_length=255)

The manage.py file is the typical Django manage.py file. Just be sure to change the settings param in os.environ.setdefault if you copy it from a fresh django-admin startproject command:

#!/usr/bin/env python
# manage.py
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
    from django.core.management import execute_from_command_line
    execute_from_command_line(sys.argv)

The settings.py file requires 3 settings: DATABASES, INSTALLED_APPS, and SECRET_KEY. Refer to Django docs for DBs that aren't SQLite:

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'sqlite.db',
    }
}

INSTALLED_APPS = (
    'data',
    )

SECRET_KEY = 'REPLACE_ME'

The real trick is in main.py, which will be where you can code against your models. Apparently you have to use wsgi to get things working with these two lines:

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Here's a sample main.py:

# main.py
# Django specific settings
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")

### Have to do this for it to work in 1.9.x!
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
#############

# Your application specific imports
from data.models import *

#Add user
user = User(name="someone", email="someone@example.com")
user.save()

# Application logic
first_user = User.objects.all()[0]

print(first_user.name)
print(first_user.email)

This project along with this post were helpful starting points for me to find the answer, and my pull request with working code for Django 1.9 was merged, so you can grab the code from masnun's repo now. If you know of a better way, please submit a pull request.

mattmc3
  • 17,595
  • 7
  • 83
  • 103
  • 1
    This answer is perfectly work in recent django-version !! Thanks:) – user3595632 Jun 28 '16 at 03:15
  • 1
    is this still relevant for 1.10.1? – waspinator Sep 21 '16 at 16:10
  • @mattmc3 It doesn't work for me in `Django 1.9.7`, I have this error `django.core.exceptions.ImproperlyConfigured: COMPRESS_ROOT defaults to STATIC_ROOT, please define either`. Do you know why? – srgbnd Nov 13 '16 at 21:06
  • 1
    @trex - I cloned the repo at https://github.com/masnun/django-orm-standalone just now and verified that it still all works for me on Python3 and Django versions through 1.10.2. Have you modified your settings.py? Maybe try to clone the repo fresh. – mattmc3 Nov 14 '16 at 00:07
  • 3
    As of Django 2.0.5 (Python 3.5) this method works, but I get runtime warnings about models being reloaded. A better solution for my setup, was replacing the two `wsgi` lines with `django.setup()`. – Austin A Jun 07 '18 at 14:29
  • https://github.com/dancaron/Django-ORM works with 3.x.x –  vrnvorona Feb 13 '21 at 14:03
11

Django 1.11 documentation on how the applications are loaded

For latest django version project structure would be-

|--myproject
|--main.py
|--manage.py
|--myapp
|   |--models.py
|   |--views.py
|   |--admin.py
|   |--apps.py
|   |--__init__.py
|   |--migrations
|--myproject
|   |--settings.py
|   |--urls.py
|   |--wsgi.py
|   |--__init__.py

You would still need manage.py to run migrations, main.py is your standalone script

# main.py
import os
import django
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
django.setup()
from myapp.models import MyModel
print(MyModel.objects.all()[0])
swapnil jariwala
  • 1,064
  • 2
  • 12
  • 19
11
import os
from django.conf import settings
from django.apps import apps

conf = {
    'INSTALLED_APPS': [
        'Demo'
    ],
    'DATABASES': {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join('.', 'db.sqlite3'),
        }
    }
}

settings.configure(**conf)
apps.populate(settings.INSTALLED_APPS)

Test on django 1.11.x

Hai Hu
  • 111
  • 1
  • 3
2

This worked for me:

import os
# replace project_name with your own project name
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")
django.setup()
from core.models import Customer,Jobs,Payments

# Your script code
obayhan
  • 1,636
  • 18
  • 35
-1

I had to add import django, and then this worked.

Joel Aufrecht
  • 442
  • 1
  • 5
  • 16