In this article, we will explain three concepts related to Django: the model-view-template (MVT) design pattern, Apps, and URLs. If we can understand these terms correctly, web programming will be much easier since we will know at all times what is happening and in which part of the code.
Before we begin, it is recommended to read the previous articles on Django since they are the previous steps to this article:
The Django MVT model works as follows:
- Data is stored in what Django calls models, which are objects with the attributes of a specific data.
- Requests are handled by views, which process the request and pass the processed data to the template through a context.
- The template displays the output to the client with the data from the view.
Django apps are similar to project modules, so we will have the code for each set of functionalities separated.
URLs are the access paths to our views, accessing a specific URL will execute the associated view.
At the moment, we only have the project created, but a project without apps is useless. We create an app for user authentication and another that will be our main application. Separating the functionalities in this way will allow us to reuse code between projects in the future.
source bin/activate
cd rxWodProject
python manage.py startapp rxWod
python manage.py startapp usersAuth
As we have explained before, views will handle the received requests and then send the processed data to the template, but in this first example, we will dispense with the template in favor of greater simplicity.
We create a view in the main app, which will respond with the text “Hello, world. You’re at rxWod: index view.”:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at rxWod: index view.")
We create a view in the user authentication app that will respond with the text “Hello, world. You’re at usersAuth: register view.”
from django.shortcuts import render
from django.http import HttpResponse
def register(request):
return HttpResponse("Hello, world. You're at usersAuth: register view.")
The Django URL system will allow us to define the entry URLs for our application. Through URLs, we will determine which requests should be handled by which views.
The main project has a URL file that refers to more specific ones in each application, thus achieving full control.
Each application must have a namespace because when the project starts to have more apps, it is very common for URLs to be repeated in the configuration of each app.
We create a URL where we indicate the view to display, in this case, the index with the namespace “rxWod”:
from django.urls import path
from . import views
app_name = 'rxWod'
urlpatterns = [
path('', views.index, name='index'),
]
We create the URL ‘register/’ for the usersAuth app, and the namespace is usersAuth:
from django.urls import path
from . import views
app_name = 'usersAuth'
urlpatterns = [
path('register/', views.register, name='register'),
]
And finally, we include them from the project’s URLs, indicating the path pattern and the URL in dotted format (rxWod/urls -> rxWod.urls):
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('', include('rxWod.urls')),
path('', include('usersAuth.urls')),
path('admin/', admin.site.urls),
]
NOTA: You can ignore the URL admin/ for now without any issue.
We restart the server.
We check the URL ‘index’.
http://127.0.0.1:8000/
And the URL ‘register’.
http://127.0.0.1:8000/register
Configuring the language is very important as it affects how dates are displayed. The timezone is equally important as it shows the correct time directly in the views.
LANGUAGE_CODE = 'es-es'
TIME_ZONE = 'Europe/Madrid'
The INSTALLED_APPS parameter in the settings.py file indicates the installed applications, which can be considered as the different functionalities of our project. Some of these applications require tables in the database. Django manages the creation of databases and tables according to the project’s needs. However, to enable Django to perform these tasks, we need to configure the access credentials to the database.
We generate a file with the access credentials for PostgreSQL. By externalizing the credentials in a text file, we can instruct Git to ignore this file. This way, the code can be published without revealing our database access credentials.
rxwod_user
PASSWORD
We change the configuration to PostgreSQL.
#DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
#}
database_auth_path = str(Path(__file__).resolve().parent) + '/database_auth.txt'
f = open(database_auth_path, "r")
lines = f.readlines()
f.close()
DB_USERNAME = lines[0].strip().split(' ')[0]
DB_PASSWORD = lines[1].strip().split(' ')[0]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'rxwod',
'USER': DB_USERNAME,
'PASSWORD': DB_PASSWORD,
}
}
We instruct Django to perform the necessary migrations (operations) in the database. This will generate a file with the commands to be executed on the database to adapt the structure to the defined models. In our case, no models have been modified, so it will not generate any new file.
No changes detected
But when we start the web server, we can read that there are migrations to apply, these are nothing more than the migrations generated by the apps such as admin, auth… all of them are internal Django apps:
*You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.*
*Run 'python manage.py migrate' to apply them.*
We apply the migrations.
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
Later, when we create or modify our models, changes will appear when executing the makemigrations command.