Django is a popular web framework built with Python that allows developers to quickly create maintainable web applications. In this tutorial, we’ll take a look at Django by getting it installed and setting up a simple project. Next, we’ll take a look at how models, URL patterns, views, and templates are used in Django to create powerful modular code for a web application. Django is a large software project with hundreds of features, but we’ll try to make it as understandable as possible. Let’s get started with Django.
What Is Django
When Looking at the official djangoproject.com website, we learn that Django as a Python web framework that allows you to rapidly develop web projects in a clean, pragmatic design. A web framework is a collection of tools used to build web applications and websites. Django comes with tools like an object-relational mapper, or ORM, which helps us make database queries. It also offers URL routing which determines what logic to follow depending on the URL of a web request. HTML templating is a another feature of Django which facilitates viewing the data as HTML in a web browser. Django itself is not a programming language. Python is the programming language that Django was built with. Django is also not a web server but it does have a built-in web server for local development.
Installing Django
You may want to set up a Python Virtual Environment to begin, but it is not mandatory. To install Django, you first need the latest version of Python installed on your machine. It is quite easy to do, by simply following the instructions at the main Python website. This will also install PIP, the package manager for Python. Once ready, all you need to do is open a terminal window and type the following command.
pip install django
This installs the latest version of Django on your computer. You can check the status of Django like so at a Python command prompt.
>>> import django >>> django.get_version() '3.0' >>>
That should be all you need to do in order to get started!
Create A Django Project
Django provides a simple command to scaffold out a new project for you. Before you run that command you want to navigate to a directory where you will store your project. For us, that will be in C:python
. From here, I’ll create the initial set of files for our Django project using a command that comes with Django which is called Django admin. To create a project, we can type django-admin.py startproject and then the name of our project. We can just call it djangotutorial. We can type out the following command and then press enter.
python $django-admin.py startproject djangotutorial
You will see that a new folder of djangotutorial is now in the current folder. In other words, we now have a Django project started in C:pythondjangotutorial
. Now, I’ll open that folder using PyCharm, a fantastic Python IDE. Here we can see the outline of files created for a new Django project.
Inside of the djangotutorial folder, there’s a file called manage.py. There is also an inner djangotutorial folder that contains four files. These are _init_.py, settings.py, urls.py, and wsgi.py. Let’s take a look at what each of these files does.
-
manage.py The manage.py file is used to run various commands for our project.
_init_.py The _init_.py file tells Python that this folder contains Python files. Also known as dunder init.
settings.py The settings.py file configures Django concepts like apps, middleware, templates, and so on.
urls.py The urls.py file is the routing file, and routes http requests based on the URL.
wsgi.py The wsgi.py, or wuzgi, file, provides a hook for web servers, such as Apache or Nginx.
With these files generated, we’re ready to run our project for the first time. We can start by navigating into the inner djangotutorial folder in our terminal. From here we can type ls and we should see the manage.py file. To run the server, we can type the command python manage.py runserver and we’ll see some output like below.
djangotutorial $python manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 17 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. January 31, 2020 - 14:45:51 Django version 3.0, using settings 'djangotutorial.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK.
The Django server is now running. We can visit http://127.0.0.1:8000/ in the browser and we should see a nice Django splash screen.
It worked! We can now see the default screen that Django makes when we create a new Django project. From here, our basic project has been generated and we’re ready to customize and add features. You might also notice that we have a db.sqllite file in the project now, that wasn’t there before. This is because when you run the runserver command for the first time, Django creates this file so that it has a database to work with.
Django Apps
A Django app is a component within a Django project. It is a folder with a set of Python files inside of it. A Django project is usually comprised of several different apps, each serving a different purpose. There may be a forum app, a wiki app, or a blog app. Each one would have its own folder within the Django project. The official docs reference creating a Polling application, and we might give that a shot in a later tutorial. For now, we’ll build an app for Dogs. We’ll call it DjangoDogs. To build out our app, we’ll go to the Terminal and navigate inside of our project to the folder where manage.py is located. Now we want to create the app. We can do this by typing the following command at the terminal.
djangotutorial $python manage.py startapp djangodogs
We can now see that several files were added, including a migrations folder. To finish adding our Django app to the project, we have one more step. We’ll need to navigate inside of the djangotutorial folder and then go to the settings.py file. Inside of the settings file, we’ll scroll down until we find the installed apps setting. At the end of this list, we’ll add the string, djangodogs. The other apps that are on this list are default apps that come with Django. We need to edit this setting whenever we install or create a new Django app. Here is the setting.py file, with our new entry highlighted.
"""
Django settings for djangotutorial project.
Generated by 'django-admin startproject' using Django 3.0.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'not_the_real_keygo^4gs&^!1d$z7d6#q=)wqx4rt0!q'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djangodogs'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'djangotutorial.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
WSGI_APPLICATION = 'djangotutorial.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
The Files of a Django App
File | Purpose |
---|---|
apps.py | Configuration and Initialization |
models.py | Data Layer |
admin.py | Admin Interface |
urls.py | URL Routing |
views.py | Control Layer |
tests.py | Tests the app |
migrations.py | Holds the migration files |
The apps.py file controls settings specific to this app. The models.py file offers Models in Django and is used to construct database schema and queries. The admin.py file defines a Django admin interface for the app where you can see and edit the data related to this app. The urls.py file can be used for URL routing specific to this app. The views.py file defines the logic and control flow for handling requests and defines the HTTP responses that are returned. The test.py file is used for writing unit tests for this app. Finally, the migrations folder holds files that Django uses to migrate the database as we create and change the database schema over time. This gives us a great overview of what an App is with regard to a Django project.
Django Routing Views Models Templates
It’s important to understand the underlying architecture when working with a web framework. Django is an MVC framework, or model view controller architecture, however, Django uses some different names for these. The four concepts to understand in Django are URL Patterns, Views, Models, and Templates. Each of these has a specific job.
URL Patterns: When a Django application receives a web request, it uses the URL patterns to decide which view to pass the request to for handling. In this project, the URL patterns are defined at djangotutorial/urls.py.
Views: A View in Django takes an HTTP request as an argument and returns an HTTP response. Our views are defined at djangodogs/views.py. Views provide the logic, or control flow portion of the project.
Models: When you want to perform queries against the database, each view can leverage Django models as needed. The models for the djangodogs app are located in djangodogs/models.py. A Django model is a class with attributes that define the schema of a database table. These classes offer built-in methods for making queries on the associated tables.
Templates: Each view that is defined can also leverage Django templates that provide the presentation layer of what the HTML response will look like. Each template is a file that consists of HTML along with extra template syntax for variables, loops, and other control flow. Template files can be placed in a folder called templates for consistency.
Configure Your Django Homepage
For this project, we want to finally render a webpage using Django. We are going to do that right now. The first thing we need to do is to add a templates directory into our djangodogs app. Here we go.
In the templates folder, we now need to add an Html file that our app can render.
Perfect. Now, we just want to add the most minimal of HTML markup so we can render a page.
djangotutorial/djangodogs/templates/home.html
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Hello Django!</title>
</head>
<body>
<h1>Hello Django!</h1>
</body>
In order to load a template, we need a view to complete this task for us. If this sounds funny to you, you can think of views in Django kind of like controllers if you are thinking about this in a more traditional MVC approach. In Django, a view is actually a controller. Here is how we can configure our views.py.
djangotutorial/djangodogs/views.py
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
In this code, we simply define a function named home(). It accepts an HTTP request and uses that to render the home.html file we just created in the prior step. You can see the render() function here takes two arguments. The first is the request, and the second is the template to display.
We can configure our urls.py like so.
djangotutorial/urls.py
from django.conf.urls import url
from djangodogs import views
urlpatterns = [
url(r'^$', views.home, name='home'),
]
The purpose of the regular expression here is to match the root URL which is a slash(/). The carrot dollar sign does the trick for us here, and it is the first argument to the url() function. Now, when the web request comes into the application, we want to trigger the home() function in the views.py file. The second parameter to url() accomplishes this goal. Lastly, we name this pattern home, which is like a named route. Now when we visit the home page of our Django project, we have success!
So we can see rendering a web page in Django is as easy as one, two, three.
from django.urls import path
Regular expressions can be a bit daunting. As such Django also offers the ability to define routes using a much simpler syntax with the path() function. Here we update our urls.py file to reflect that change, and everything still works perfectly.
djangotutorialdjangotutorialurls.py
from django.urls import path
from djangodogs import views
urlpatterns = [
path('', views.home, name='home')
]
Passing an ID via a Route
The combination of home url, view, and template above would likely be used to display a listing of dogs. It is like the home page for the dogs resource. Now, what about when you want to drill down on one item in the collection and view details about that item? In this case, if we want to view the specific details about a Dog, we want to pass along an ID via the url pattern. Imagine we have 10 different dogs in the database and each has a unique ID. We can pass that ID and get those details. Here is how we can set that up.
djangotutorialdjangotutorialurls.py
from django.urls import path
from djangodogs import views
urlpatterns = [
path('', views.home, name='home'),
path('dogs/<id>/', views.dog_detail, name='dog_detail'),
]
The snipped above is saying what we can visit an url like https://mysite.com/dogs/7 – and that would send the ID of 7 along in the request. In our views.py file, we can test this out by returning an HttpResponse along with the given id.
from django.shortcuts import render
from django.http import HttpResponse
def home(request):
return render(request, 'home.html')
def dog_detail(request, id):
return HttpResponse(f'<h1>Dog with id {id}</h1>')
This shows how passing an ID via the URL works in Django. Now, once we have a database implemented, we can use that ID to query the database to get details about a given Dog.
Passing Data To Template From View
Instead of returning an HttpResponse directly from the view, let’s now render a template file and pass the data from the function in the view to the template. We’ll also display the ID in that template using interpolation.
djangotutorialdjangodogsviews.py
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
def dog_detail(request, id):
return render(request, 'dog_detail.html', {'id': id})
djangotutorialdjangodogstemplatesdog_detail.html
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Dog Detail!</title>
</head>
<body>
<h1>Dog with id of {{ id }}</h1>
</body>
Introducing Django Models
Models refer to the data layer of a Django application. The concept is familiar if you have worked with any type of MVC project in various programming languages or frameworks. The Model is what defines the structure of our data and how it will be stored in the database. Django has a built-in Object Relational Mapper, or ORM, that you can use to easily put data into, and get data out of the database. A given Django application has a models.py file, and this is where the Models for our application are defined. You can have one or many in the same file. In Django, a Model is a class that inherits from Django.db.models.Model. Models use class attributes to define their fields. We just want to add a few fields so that we can track the name, breed, and description of each Dog in our Django application.
djangotutorialdjangodogsmodels.py
from django.db import models
class Dog(models.Model):
name = models.CharField(max_length=100)
breed = models.CharField(max_length=30, blank=True)
description = models.TextField()
Django Migrations
Django models define the expected structure of our database. Migrations are responsible for creating the necessary scripts to change this structure through time as a project evolves. In Django, when you add a Model to the models.py file, the related database table does not yet exist. When a new model is created, an initial migration creates the database table. Migrations are also needed when a field is added or removed from an existing model, or when attributes of a field have changed. All of these changes to a models.py file need a corresponding change to the database and for this purpose, a migration needs to be created and run. What is nice in Django is that you do not have to manually create the migration, it is generated by Django for you. The way this works is you have to define the Model yourself, then use the makemigrations
command to generate migrations files. This command reads the current models file and inspects the current state of the database to determine what changes need to be made to make the database structure match the models.py file. Migrations are needed in all of the following cases.
With our Model defined above, we can now make our initial migration using the command python manage.py makemigrations. We should see output similar to below.
djangotutorial $python manage.py makemigrations Migrations for 'djangodogs': djangodogsmigrations001_initial.py - Create model Dog
There is now an a file named 0001_initial.py in the application, and the auto generated code from Django looks like so.
djangotutorialdjangodogsmigrations001_initial.py
# Generated by Django 3.0
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Dog',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('breed', models.CharField(blank=True, max_length=30)),
('description', models.TextField()),
],
),
]
Django itself has many migrations already built in and we can view the migrations using the python manage.py showmigrations command. This builds out the tables for things like the authentication system among others. The key piece of information to note from the output below is that we now have the 0001_initial migration that is a custom defined migration in the djangodogs application.
djangotutorial $python manage.py showmigrations admin [ ] 0001_initial [ ] 0002_logentry_remove_auto_add [ ] 0003_logentry_add_action_flag_choices auth [ ] 0001_initial [ ] 0002_alter_permission_name_max_length [ ] 0003_alter_user_email_max_length [ ] 0004_alter_user_username_opts [ ] 0005_alter_user_last_login_null [ ] 0006_require_contenttypes_0002 [ ] 0007_alter_validators_add_error_messages [ ] 0008_alter_user_username_max_length [ ] 0009_alter_user_last_name_max_length [ ] 0010_alter_group_name_max_length [ ] 0011_update_proxy_permissions contenttypes [ ] 0001_initial [ ] 0002_remove_content_type_name djangodogs [ ] 0001_initial sessions [ ] 0001_initial
Everything is now in place for us to run the migrations. We can do this using the python manage.py migrate command like so.
djangotutorial $python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, djangodogs, 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 djangodogs.0001_initial... OK Applying sessions.0001_initial... OK
When we first ran the showmigrations command, we saw a [ ] at the beginning of each migration. This means that the migration exists, but has not yet been run. If there is a [x] to the left of each migration, that means the migration has been run. We can use the python manage.py showmigrations command one more time to display the migrations and verify that they have been run successfully.
djangotutorial $python manage.py showmigrations admin [X] 0001_initial [X] 0002_logentry_remove_auto_add [X] 0003_logentry_add_action_flag_choices auth [X] 0001_initial [X] 0002_alter_permission_name_max_length [X] 0003_alter_user_email_max_length [X] 0004_alter_user_username_opts [X] 0005_alter_user_last_login_null [X] 0006_require_contenttypes_0002 [X] 0007_alter_validators_add_error_messages [X] 0008_alter_user_username_max_length [X] 0009_alter_user_last_name_max_length [X] 0010_alter_group_name_max_length [X] 0011_update_proxy_permissions contenttypes [X] 0001_initial [X] 0002_remove_content_type_name djangodogs [X] 0001_initial sessions [X] 0001_initial
python manage.py shell
We can test our new Model out now. We need to use the shell via the python manage.py shell command. We can add our first dog to the system like so.
Insert Record Into Database
djangotutorial $python manage.py shell Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:21:23) [MSC v.1916 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from djangodogs.models import Dog >>> dog = Dog(name='Winnie', breed='Havanese', description='Fun loving female!') >>> dog.save()
Retrieve Record From Database
We did not get any errors when inserting our first record into the database using the Django ORM. To query the database using the ORM so we can view that record, we can use these commands.
>>> dogs = Dog.objects.all() >>> dog = dogs[0] >>> dog.name 'Winnie' >>> dog.breed 'Havanese' >>> dog.description 'Fun loving female!'
Once we add another record to the database, the .all() command returns more than one result.
>>> Dog.objects.all() <QuerySet [<Dog: Dog object (1)>, <Dog: Dog object (2)>]>
URL -> View -> Model -> Template
We can put it all together now. When we visit the homepage, we want to display all Dogs. We should be able to click the dog name, and Django will load the detail template to show the details of each particular dog. This is the updated home() function in the views.py file to list all Dogs.
djangotutorialdjangodogsviews.py
from django.shortcuts import render
from .models import Dog
from django.http import Http404
def home(request):
dogs = Dog.objects.all()
return render(request, 'home.html', {'dogs': dogs})
The home.html template must also now be updated to allow us to loop over any number of dogs in the system. Django provides special tags in the templating language to allow for this.
djangotutorialdjangodogstemplateshome.html
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Hello Doggies!</title>
</head>
<body>
{% for dog in dogs %}
<a href="{% url 'dog_detail' dog.id %}">
<h1>{{ dog.name|capfirst }}</h1>
</a>
{% endfor %}
</body>
Visiting the homepage shows that we now see the small listing of Dogs in the system! Also notice that each dog is clickable, with the correct ID used in the href.
To ensure the ability to click on each Dog works, we need to update the dog_detail() function in the views.py file. Here is the updated code which now uses the ID provided to fetch a given Dog from the database using the Model we created.
djangotutorialdjangodogsviews.py
from django.shortcuts import render
from .models import Dog
from django.http import Http404
def home(request):
dogs = Dog.objects.all()
return render(request, 'home.html', {'dogs': dogs})
def dog_detail(request, id):
dog = Dog.objects.get(id=id)
return render(request, 'dog_detail.html', {'dog': dog})
The last step now is to simply update the dog_detail.html template file to display the details of one particular dog.
djangotutorialdjangodogstemplatesdog_detail.html
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Dog Detail!</title>
</head>
<body>
<h1>Dog with id of {{ dog.id }}</h1>
<h2>This dogs name is {{ dog.name }}</h2>
<h2>The breed of this dog is {{ dog.breed }}</h2>
<h2>Description: {{ dog.description }}</h2>
</body>
Our finished mini-application is working well 🙂
Learn More About Django
- Everything you need to know about Django (docs.djangoproject.com)
- Django For Beginners (djangoforbeginners.com)
- Django For Babies (dev.to)
- Beginning Django Tutorial (djangobook.com)
- Python Django Tips and Tricks (letslearnabout.net)
- Django Tutorial For Beginners (guru99.com)
- Github Repo For Django Beginners (github.com)
- How To Get Started With Django (realpython.com)
- The Top Tutorials For Django Beginners (medium.com)
- Django and Python for Beginners (simplifiedpython.net)
- Django Tutorial (data-flair.training)
- Django Complete Guide For Beginners (simpleisbetterthancomplex.com)
Django For Beginners Summary
If you made it all the way through this Django for beginners tutorial, congratulations! You are now on your way to putting the power of Python and Django to work for you in new and exciting ways. When choosing a Web Framework to work with, Django is the leading choice for Python web developers. In this tutorial, we covered a lot of ground including:
- What Django Is
- Getting Django Installed
- Creating A Django Project
- How To Create Django Apps
- The Files of a Django App
- Django Routing, Views, Models, and Templates
- Configuring Your Django Homepage
- URL Routing
- Passing an ID via a Route
- Passing Data To a Template From a View
- Django Models
- Django Migrations
- Inserting Records Into the Database
- Retrieving Records From the Database
- Additional Resources For Django