# Django in one file? Or should i call it a mini Django?

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

1. Running Django inside a single file
    
2. 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716061430465/99e8f4c8-8602-4e7f-8a9c-f789680d39d9.png align="center")

Reference: [https://stackoverflow.com/a/59356081/7587197](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.

1. `urls.py`
    
    ```python
    urlpatterns = []
    ```
    
2. `views.py` (empty file for now)
    
3. `manage.py` (The main entry file)
    
    ```python
    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.
    

```python
# views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world.")
```

```python
# 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716065180214/5b7afc54-a6b8-4da1-b8b1-c6b309952cfa.png align="center")

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

1. `apps.py`
    
    ```python
    from django.apps import AppConfig
    
    # just a random name, MDJ=mini django
    class MDJConfig(AppConfig):
        name = 'mdj' # name of the root folder
    ```
    
2. `models.py`
    
3. `migrations package` (`migrations` folder and an empty `__init__.py` file)
    

and register this apps config location on settings(`manage.py file`), `INSTALLED_APPS` as

```python
# 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

```python
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

```python
# 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`)

```python
# 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716067810228/d7ebccd6-25a3-4061-96b2-0ceaf46d46f9.png align="center")

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 when `python manage.py makemigrations` command is used)
    

The final `manage.py` looks like this

```python
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 ?

1. Change `models` to `database` which can be done by changing `MODELS_MODULE_NAME` on `django/apps/config.py:10` Doing this, the app will now know it needs to load models from `database.py` file instead of `models.py`
    
2. Changing `migrations` to `databasehistory.` To make this work series of changes needs to be done on `django.core.management.commands.makemigrations.py` file and `django.db.migrations.writer.MigrationWriter`. I still need to verify doing this myself, since i see lots of things are changed on Django core itself.
    
3. 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 add `app_label` if `db_table` for model is not given
    
4. When (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 files
    
5. When performing all this fixes, create fix and patch it in runtime through `manage.py` file
    

Find complete code at: [https://github.com/shrawanx/mdj](https://github.com/shrawanx/mdj)

### At the end, i feel this current implementation has lots and lots of works to do before i can say what the title of this article says, but it was fun trying and experimenting. Happy weekend
