thegiffman thegiffman - 5 months ago 17
Python Question

Will using the Django ORM in a python library cause trouble?

I've enjoyed using Django quite a bit over the years. Right now I'm working for a company that is building some shared internal libraries for accessing information from our databases. Right now things are terribly sloppy - lots of inline SQL code. Some colleagues were working on doing some accessing code, and it occurred to me that this is the sort of thing that I'm used to Django doing out of the box. I had also heard that Django is fundamentally modular, so that I could just use the ORM system in isolation. I know there are other packages for this like SqlAlchemy, but I also hear that Django does things easier for the average case, which is likely all we'll need. I also know Django, and don't know SQLAlchemy.

So, I can do a proof of concept, like the following. Here is the directory structure:

+-- example.py
+-- transfer
| +-- __init__.py
| +-- models.py


Here is models.py

import django.conf
import django.db.models

django.conf.settings.configure(
DATABASES = ..., # database info
INSTALLED_APPS = ("transfer",),
SECRET_KEY = 'not telling',
)
django.setup()

class TransferItem(django.db.models.Model)
# model info here


example.py

from transfer.models import TransferItem
items = TransferItem.objects.all()
print items


This seems to work fine, as far as it goes. But I'm worried about the bootstrap code in a library context. Specifically:


  1. Is there danger in django thinking of this as an app? In this case, "transfer" is a root module, but in a library context this could be buried deep. For example, "mycompany.data.protocols.transfer". Theoretically, we could have these data models defined throughout the codebase. How can this "app list" scale?

  2. The call to setup really worries me. The django docs specifically say only to call setup once. And yet the nature of a library is that any python application could import whatever type of data model they want. I can't make any assumptions about which django "apps" they might want, or what order they want it in. Would if one type of model is used, data is returned, and only then does the python application decide it needs to import another type of model (quite possibly in a different "app")?



So, the fundamental question is this:

Is there a good way to use django ORM in a python library?

EDIT: This is not a duplicate of the CLI tool question. I know how to run django outside the web server. I even gave code samples showing this. I want to know if there's a way to run django where I don't have "apps" per se - where model files could be imported by client code and used in any order.

Answer

OK, here's my own attempt to answer the question after some research.

I can create a baseclass for my models anywhere in the library as follows:

from django.db import models
from django.apps import apps
import django.conf

django.conf_settings.configure(
    DATABASES = ...
)

apps.populate((__name__,))

class LibModel(models.Model):
    class Meta:
        abstract = True
        app_label = __name__

Then anywhere in the library I can create my own models with this baseclass. Since I'm not relying on the "app" for the database names, I need to state them explicitly.

class SpecificModel(LibModel):
    # fields go here
    class Meta(LibModel.Meta):
        db_table = "specific_model_table_name"

This gets around my concern of having to simulate the structure of an "app". The name property in the base class supplies Django with all it needs, and then Django quits whining about not finding an app. The other model files can live wherever they want.

However, there is still a big concern I have which might be lethal. Django's initialization itself is still singleton in nature. If my library were itself imported by a Django application, it would all crash and burn. I'll ask about solutions to this in a follow up question.

Comments