Django in one file? Or should i call it a mini Django?
Nothing serious, just experimenting on Django Framework
It's weekend and after a very busy week i am back in my home desk and navigating through my checklist. Though i had not put any priority on my checklist, my eye went to A Simple Django version for beginners
. Frankly i forgot what was my real idea over it, but i know few of them
Running Django inside a single file
Simple file and folder structure
Running Django Inside a Single File
I came up with my own solution from my stackoverflow answers. See Screenshot below.
Reference: https://stackoverflow.com/a/59356081/7587197
So looks like Django in a single file is possible. Here, your views and URLs are inside this same file, but we face problem when dealing with models inside this file since Django works on App concept
and has its own guidelines on implementing apps like creating apps.py
models.py
migrations package
and so on
so now let's try to make it more readable and usable.
Simple file and folder structure
So, continuing from the single file solution, lets create couple of files to make the code readable. (I am assuming the root folder is mdj
) so this means every files will stay inside it.
urls.py
urlpatterns = []
views.py
(empty file for now)manage.py
(The main entry file)import sys SETTINGS = dict( SECRET_KEY='djangoISsoCOOL', DEBUG=True, ROOT_URLCONF='urls', # so that it can denote urls.py INSTALLED_APPS=[], ) if __name__ == "__main__": import django from django.conf import settings from django.core.management import execute_from_command_line settings.configure(**SETTINGS) django.setup() execute_from_command_line(sys.argv)
lets run this with command
python manage.py runserver
and it works. Now, lets create a simple page to check if view and urls works.
# views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world.")
# urls.py
from django.urls import path
import views # import the view
# Todo for you : try with other import style as well
urlpatterns = [
path('', views.index),
]
Now, run the server again using python manage.py runserver
and it works.
Now, let's make the model and database to work, but we will need to configure app for this, so create few files to configure
apps.py
from django.apps import AppConfig # just a random name, MDJ=mini django class MDJConfig(AppConfig): name = 'mdj' # name of the root folder
models.py
migrations package
(migrations
folder and an empty__init__.py
file)
and register this apps config location on settings(manage.py file
), INSTALLED_APPS
as
# manage.py
SETTINGS = dict(
...
INSTALLED_APPS=[
'apps.MDJConfig',
],
...
)
Now, lets run the server using, and it did not work this time and we see the error as ModuleNotFoundError: No module named 'mdj'
this means, the module, which we assumed to be the root of our project, is not being recognized. So, lets add out root folder path
into systems path
so that it can be recognized.
Add these following in the manage.py
file
import sys
from pathlib import Path
# BASE_DIR = parent of manage.py file
BASE_DIR = Path(__file__).resolve().parent
# this line will do the magic
sys.path.append(str(BASE_DIR.parent))
And now, run the server, and it works.
now let's create our very first sample model
# models.py
from django.db import models
class Sample(models.Model):
name = models.CharField(max_length=100)
Create migrations using command: python manage.py makemigrations
and it works, the migration is created and placed under migrations folder
Now, before applying migrations, configure database (sqlite3 for demo
)
# manage.py
SETTINGS = dict(
...
DATABASES={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
...
)
and apply migrations using command python manage.py migrate
and everything works, the database is created and the migrations are reflected in the database.
Open up Django shell using command python manage.py shell
to play with the model.
So, the final structure of the project will look like this,
manage.py (core entry point contains settings as well)
urls.py (all urls for the project)
views.py (all view functions and classes for the project)
apps.py (app level configurations)
models.py (the model file which contains db related works)
migrations/__init__.py (
migrations
folder and the empty__init__.py
file to store migrations whenpython manage.py makemigrations
command is used)
The final manage.py
looks like this
import sys
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
sys.path.append(str(BASE_DIR.parent))
SETTINGS = dict(
BASE_DIR=BASE_DIR,
SECRET_KEY='djangoISsoCOOL',
DEBUG=True,
ROOT_URLCONF='urls', # so that it can denote urls.py
INSTALLED_APPS=[
'apps.MDJConfig',
],
DATABASES={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
)
if __name__ == "__main__":
import django
from django.conf import settings
from django.core.management import execute_from_command_line
settings.configure(**SETTINGS)
django.setup()
execute_from_command_line(sys.argv)
What next ?
Change
models
todatabase
which can be done by changingMODELS_MODULE_NAME
ondjango/apps/config.py:10
Doing this, the app will now know it needs to load models fromdatabase.py
file instead ofmodels.py
Changing
migrations
todatabasehistory.
To make this work series of changes needs to be done ondjango.core.management.commands.makemigrations.py
file anddjango.db.migrations.writer.MigrationWriter
. I still need to verify doing this myself, since i see lots of things are changed on Django core itself.default app name should not be appended when creating table name for models. To make this work, changes are required on
django.db.models.options.Options.contribute_to_class
to not addapp_label
ifdb_table
for model is not givenWhen (3) is fixed, root folder name can be changed to any without any problems. currently, root folder name is
mdj
which is hardcoded on some of the filesWhen performing all this fixes, create fix and patch it in runtime through
manage.py
file
Find complete code at: https://github.com/shrawanx/mdj