one I've written few years ago. Special shoutout and thanks and hugs and kudos to Javier Buzzi for taking the time to improve the original script.
TL;DR: download old version & download new version
The content associated with mlvin.xyz may be very offensive to some people. I've lost the ownership of mlvin.xyz a very long time ago, sad situation. I'm not anymore linked to this domain name, nor to the content hosted on this website. By the way F*** OVH.
Our models are not defined as in a classical Django application. So, each model should declare which app it belongs to. You can read more about app_label Meta option here.
The problem with the first script was duplication:
class Author(models.Model):
name = models.CharField(max_length=200)
class Meta:
app_label = APP_LABEL
class Book(models.Model):
author = models.ForeignKey(Author, related_name='books')
title = models.CharField(max_length=400)
class Meta:
app_label = APP_LABEL
We want to define app_label once and for all our models:
# The current name of the file, which will be the name of our app
APP_LABEL, _ = os.path.splitext(os.path.basename(os.path.abspath(__file__)))
Then, we need to overwrite the Django function in charge of:
This function is named get_containing_app_config
def get_containing_app_config(module):
if module == '__main__':
# if inside single file project,
# retrieve the application configuration using APP_LABEL variable
return apps.get_app_config(APP_LABEL)
# otherwise, do as you always do
return apps._get_containing_app_config(module)
# save the original function
apps._get_containing_app_config = apps.get_containing_app_config
# ask Django to use our custom function
apps.get_containing_app_config = get_containing_app_config
There is a Django settings named MIGRATION_MODULE. According to the documentation:
A dictionary specifying the package where migration modules can be found on a per-app basis. The default value of this setting is an empty dictionary, but the default package name for migration modules is ``migrations``.
In the first version of the script, all the migrations were put in a folder named migrations
. With the following configuration, we can:
# Where migrations folder need to be created
APP_MIGRATION_MODULE = '%s_migrations' % APP_LABEL
APP_MIGRATION_PATH = os.path.join(BASE_DIR, APP_MIGRATION_MODULE)
# Create the migration folder
# and a __init__.py file if necessary:
if not os.path.exists(APP_MIGRATION_PATH):
os.makedirs(APP_MIGRATION_PATH)
open(os.path.join(APP_MIGRATION_PATH, '__init__.py'), 'w').close()
We also took the time to update the Django settings, somewhere inside the call to settings.configure function
, you'll find:
# Django needs to be told where is the migration module
MIGRATION_MODULES={APP_LABEL: APP_MIGRATION_MODULE},
A correctly configured Django application should normally have a model modules
, a urls modules
and a tests module
. Python provides us with an interesting class: types.ModuleType
, that will help us create a module, you guessed it:
# Used so you can do 'from <name of file>.models import *'
models_module = ModuleType('%s.models' % (APP_LABEL))
tests_module = ModuleType('%s.tests' % (APP_LABEL))
urls_module = ModuleType('%s.urls' % (APP_LABEL))
# we created the urlpatterns list earlier,
# let's attach this variable to the urls_module:
urls_module.urlpatterns = urlpatterns
# A model module needs to have classes that inherits from models.Model
# let's correctly add all our models we defined earlier
# as attributes to the models_module:
for variable_name, value in list(locals().items()):
# We are only interested in models
if inspect.isclass(value) and issubclass(value, models.Model):
setattr(models_module, variable_name, value)
# Setup the fake modules
sys.modules[models_module.__name__] = models_module
sys.modules[urls_module.__name__] = urls_module
sys.modules[APP_LABEL].models = models_module
sys.modules[APP_LABEL].urls = urls_module
I really hope you've learned something, I did \o/. You may want to browse some of the gists kept by Javier Buzzi.
You may also be really interested by the work done for django-micro a lightweight wrapper around Django that turns it into a microframework.
If you have any kind of interesting improvements, advices, suggestions, please send me an email, or post a comment on Mastodon. Still not took the time to install a comment system, shame on me.
o/