Why Django REST Framework (DRF) folder structure is different than Django Turorial?

Viewed 3197

If you follow the Django Tutorial here you'll run theses commands:

django-admin startproject mysite
# Change into the outer mysite directory
cd mysite
python manage.py startapp polls

and you'll get this folder structure

mysite/
├── manage.py
│
├── mysite/
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
│
└── pools/
    ├── migrations/
    │   └── __init__.py
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── tests.py
    └── views.py

But if you follow Django REST Framework here and you'll run these commands:

Note: I replaced the directory names to match, for better comparison

# Create the project directory
mkdir mysite
cd mysite
# Set up a new project with a single application
django-admin startproject mysite .  # Note the trailing '.' character
cd mysite
django-admin startapp polls
cd ..

and you'll get this folder structure

mysite/
├── manage.py
│
└── mysite/
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    ├── wsgi.py
    │
    └── polls/
        ├── migrations/
        │   └── __init__.py
        ├── __init__.py
        ├── admin.py
        ├── apps.py
        ├── models.py
        ├── tests.py
        └── views.py

This is DFR's explanation:

It may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external modules (a topic that goes outside the scope of the quickstart).

What I want to know is more about this "topic that goes outside the scope of the quickstart". I would like to read up on more of this topic and have some examples. Also why does Django Tutorial teaches something that "apparently" has problems and "apparently" you shouldn't do.

1 Answers

If you follow the Django REST framework tutorial, you will indeed end up with the directory you describe. In the documentation we see that the file structure looks like:

.
./manage.py
./tutorial
./tutorial/__init__.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py

If we put that in a tree structure, we see:

.
├── manage.py
└── tutorial
    ├── __init__.py
    ├── quickstart
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

But this is not the same code structure that the Django tutorials use, in that case we create the project structure with:

# Create the project directory
mkdir mysite
cd mysite

# Set up a new project with a single application
django-admin startproject mysite .
#  no cd mysite
django-admin startapp polls
cd ..

then the project directory looks like:

.
./manage.py
./tutorial
./tutorial/__init__.py
./quickstart
./quickstart/__init__.py
./quickstart/admin.py
./quickstart/apps.py
./quickstart/migrations
./quickstart/migrations/__init__.py
./quickstart/models.py
./quickstart/tests.py
./quickstart/views.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py

or thus as a filetree:

.
├── manage.py
├── quickstart
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── tutorial
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

You thus call django-admin startapp polls in the root directory, so the outer mysite directory, not the inner mysite.

The reason that the Django REST framework advices this extra layer is to avoid name clashes. If you for example would like to name an app zipfile, then this clashes with the module of the zipfile package [Python-docs], so then your modules can no longer reference items of the zipfile package.

By nesting these in the project name, you thus will makes these modules available as from nameofawesomeproject.zipfile, and thus you can still import zipfile for the package.

The app labels however do not change automatically: the name of the app is by default the name of the deepest nested module name, so for django.contrib.auth, it is auth. You can set a different name by implementing an AppConfig for your project.

Related