How to create Django Project Layout? (pt.1 )

The examples in my article are not perfect design patterns - they are made to be used as guidelines for structurizing your project. They will create a logical structure and will guide us through the folder structure and files.

Environment setup

At the very beginning you need to think about how you want to work with the project to maintain the order in your system and to avoid conflicts with other projects. It’s not important whether you already have Django installed on your computer or are only planning to do so. It gets more complicated, however, when you want to work with version of Django that differs from the one that was used in projects that are stored on your hard drive already. Of course, while you are not using additional modules, you can easily reinstall Django to the required version. You can also do the same thing with Python. However, to get around this problem, you can use the virtual environment called virtualenv. Its task is to isolate specific versions of Python, Django and other modules in a way that they won’t affect other projects. This can be compared to a cabinet where you put all the necessary things to isolate them from the rest of your stuff. You can have an infinite number of such “cabinets” that can be opened any time you want. That way you can keep each project’s settings separately.

You can install virtualenv by following the instructions on its official website. The next step will be to create a first environment for our project. To do this you need to go to console and then to the folder of your choosing (in which a new directory named after our virtual environment will be created). Execute the command:

virtualenv --python=python3.4 myenv

Our virtual environment is called myenv and it will be unique to every project. To run it and activate our new environment you need to execute this command:

source myenv/bin/activate

Note that the created folder has the same name as our virtual environment.

If everything is done correctly, the following prefix should appear in console:

(myenv) ~/projectname$

Repetitive typing of the virtualenv’s activation path is not very effective and can be optimized thanks to virtualenvwrapper. To use it you will need virtualenv.

Now we can create a virtual environment using the following command (the principle of operation is the same as in the case of virtualenv, but this time we are going to use the wrapper):

mkvirtualenv --python=/usr/bin/python3 myenv

If you encounter an error during the execution of the command above, use a different name of a virtual environment (eg. myenv_project). The error is caused by the already existing virtual environment with the same name.
In this case, we don’t need to go to the directory (where we will create a project and run virtualenv) to generate an appropriate set of configuration files of the virtual environment. These files are grouped in the folder defined during the installation of this addon. We no longer need to activate the environment through the path, but only through the command:

workon myenv

Similar to the virtualenv, prefix will be added in the console.

Right now we have to install the preferred Django version in our environment.

Overview of the default project structure

If you didn’t have contact with Django before, you have to look at the basic structure of the project. Django can generate the necessary elements of the directory by using the following command (execute it in the directory that you want to create a website in):

django-admin startproject mysite

mysite is a name of any directory name in which necessary subdirectories and files are going to be created.

As a result of the above command you will receive the following project structure:

mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
Wsgi.py

If you don’t want to create additional directory called “mysite”, you can end the command with a full stop.

django-admin startproject mysite .

Thanks to that the whole structure of our project will be built in the directory. This means that our project will look like that:

your_folder/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py

This is due to the fact that the name of the main folder does not matter to Django and can take any value. However, you need to pay attention to the name of the "mysite" folder. This is where the site configuration is stored Let's have a look at each of those files:

  1. __init__.py – usually it’s an empty file that signals that folder is a package. You can read more about this on Python’s official website;
  2. settings.py – it’s a file that contains all settings of the project that allow for running a website and configuration of (for instance) database;
  3. urls.py – this is where URL patterns are placed, which are used for routing pages to particular paths;
  4. wsgi.py – contains all the WSGI settings, which may interest us during installation of the website on an external server.

Modifying the settings.py file

If you visit settings.py file, you will see that all essential parts were written and prepared so we can quickly modify them. For a start it is worth to set the timezone. In my case it will be:

TIME_ZONE = 'Europe/Berlin'

Then, if necessary, you can modify the database settings or keep default values:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}

In addition to that you must indicate under what address static files have to be stored and in which folder they are to be searched. You can do this by entering the following settings:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

It is a good idea to take a look at the tuple named INSTALLED_APPS. In it we print the names of all applications, which we will be using in the project. It is important that after each name entered in string form (e.g. “my_app,”) we add comma. I will talk more about how to create your own application later in this article.

Now we just need to create the necessary tables in the database. We can do this with the following command:

python manage.py migrate

After all these steps, project can now be ran locally.

Structure of application

It may seem that this is all that Django can do when it comes to the project generation. It turns out, that there is another element which I didn’t mention - applications. They are additional folders with any name, dividing the project into smaller parts. As a result, your work will be easy to understand by every developer. You will not have to search through multi-line files to find a functionality you are interested in at the moment. Additionally, Django meets the needs of developers and creates an application structure with the following command:

python manage.py startapp myapps

myapps is the name of our application - we should add it to INSTALLED_APPS

The command above will generate the following structure:

mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
myapps/
migrations/
__init__.py
__init__.py
admin.py
models.py
tests.py
views.py

Let’s take a look at each of these files:

  1. __init__.py - it’s the same as before;
  2. admin.py - in this file you can configure the admin panel, making it easy to manage the database and the content of the website;
  3. models.py - this is where we create code that represents database schema, allowing us to create tables without using SQL;
  4. tests.py - we put code that tests our application here;
  5. views.py - here we have to create the user interface layer in accordance with the MVC assumptions.

It’s also a good idea to create the additional forms.py file, which we should put in our application. In this file all application forms will be stored.

In future each application will probably include template files (eg, HTML), which should be placed in the "templates" folder inside the application. This might look like this:

mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
myapps/
templates/
myapps/
any.html
migrations/
__init__.py
__init__.py
admin.py
models.py
tests.py
views.py

If you have a keen eye you will notice that I added the additional folder (called like our application) and then placed in it the file with the HTML extension. This arrangement is a matter of convention, but it allows you to keep order in the project.
It’s also worth to create the templates folder that will be available throughout the project area. In it you should keep html templates that can be used by multiple applications. It will look like this:

mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
myapps/
templates/
myapps/
any.html
migrations/
__init__.py
__init__.py
admin.py
models.py
tests.py
views.py
templates/

Django might not see our templates. This problem can be solved by supplementing the TEMPLATES list located in settings.py:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Keep in mind that Django does care which templates have html or txt extensions. You should, however, keep the one extension that correctly describes the contents of the file.

What’s next?

It may seem that we basically did everything we could to make our project clear and functional. Indeed, the structure created is useful and understandable. Unfortunately, sometimes you can notice that repeating the same scheme to create the project becomes boring and ineffective. What is discussed in this part of the article is useful for beginners in Django development and helps them to understand it. However, we should go a step further and use the ready-made structures/templates of the project - I will talk about it in the second part of my article, which will soon be published on our blog. Follow us on Facebook, Twitter and LinkedIn to avoid missing it out!

Navigate the changing IT landscape

Some highlighted content that we want to draw attention to to link to our other resources. It usually contains a link .