Your Intro to Django (2020)
Tags: django, python, webdev
Published: 2020-04-21 14:09:32

### Introduction

The popular Python web framework can be a little daunting to new and experienced web developers alike.

However, as the backbone of Instagram, Spotify, YouTube, DropBox, Pinterest and a huge number more, Django serves as a beautiful tool for startups and large enterprises alike to develop successfully and agiley.

In this intro, we're going to give you a briefing on Django so that you can move on to project tutorials confidently.

---

## Background

### Web Servers

A web server’s job is to serve you web pages. 

When you visit a URL, you are effectively asking for the web server to serve you an HTML document. 

Theoretically, we’re able to run any program code we desire in order to generate the HTML document. This allows us to use language features, such as variables and functions, in order to generate pages.

However, it would be hard for entire teams to work on a large website without constant merge conflicts. 

Django’s solution is the model-template-view architectural software pattern. 

In basic terms:

- A template contains the display logic (HTML) for the webpage.
- A view will combine the template with variables to generate a page.
- A model can be used to grab data from the database for the view.

There's one more layer to this architecture, which is the `routes`. A route is a path from a URL to either a resource or another route. 

Routes allow us to create some logic in how to get to a particular file, without the user having to request its absolute file path as a URL.

---

## Getting Started

### Making a Project

Installing Django is as simple as running `$ pip install django`.

Once Django has been installed, we’ll have access to the `$ django-admin` command and its subcommands.

We can now generate our project using `$ django-admin startproject`.

It’s important now to establish that Django is a framework that offers tools for building a web application **as well as** tools for running a web server for it.

When we ran `startproject`, the `website/` directory and `manage.py` file were created.

- The `website/` directory is where our web application and web server files are stored.
- The `manage.py` file is a tool for running and managing the web server through the command line.

### Project Files

The `website/` directory contains the following files by default:

- **__init__.py**: the Python package details, which will currently be blank.
- **settings.py**: the settings and configuration details for the project.
- **urls.py**: the list of paths to map URLs to views.
- **wsgi.py**: a Django file used to communicate to the web server.

We could theoretically create the `views.py`, `models.py` and `template.html` within this folder. 

However, it's both a developer's convention and a Django convention to create an app within our project to start building.

Django can run a web server with a welcome page straight out of the box.

We can launch this in its entirety with a single command: `$ python manage.py runserver`. This will now serve web files from `localhost`, which hosts the Django website by default on port `8000`.

---

## Starting Development

### Apps

In Django, a project consists of apps, where each app serves its own function. 

This helps us to avoid the monolithic approach of developing the whole project within a single folder. Another benefit of this is the ability to copy an app straight from one project to another.

We can generate our app using `$ django-admin startapp`.

This will create an app directory that's similar to `website/`. However, the app contains files for the webpage logic, such as `views.py` and `models.py`.

### Views

Let’s quickly cover some networking.

In order to ‘visit’ a web page, a client sends an HTTP request to the web server. If the request can be successfully fulfilled, an HTTP response is returned containing HTML code.

Therefore, our view’s job is to return an HTTP response containing some generated HTML.

Thankfully, this is a single function call within Django.

```python
from django.http import HttpResponse

def home(request):
    return HttpResponse('<h1>Hello, world!</h1>')
```

### Routes

Routing from our project's `routes` to an app's `routes` in quite simple.

```python
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app/', include('app.urls')),
]
```

Within our app, we need to make a `urls.py` file, which we can copy from the `urls.py` in `website/`.

```python
from django.urls import path
from . import views

path('', views.about, name='app-home'),
path('about/', views.about, name='app-about'),
```

Now, a request for /app/about will route all the way from our project root to the `about` view.

---

## Further Development

### Templates

Templates are just HTML files. Django will look for them in `app/templates/app/\*.html`.

We include them within views by using the `render()` function:

```python
def home(request):
    return render(request, 'app/index.html')
```

The contents of `app/index.html` would be something like:

```html
<!DOCTYPE html>
<html>
<body>
  <p>Welcome to the Home page.</p>
</body>
</html>
```

Django Template Language (DTL) code can be thrown in with the HTML code in order to handle variables, command blocks and other Python features.

```html
<!DOCTYPE html>
<html>
<body>
  <p>Welcome to the {{ title }} page.</p>
</body>
</html>
```

In order to pass a variable, such as `title`, into the template, `render()` takes a third argument.

```python
def home(request):
    return render(request, 'app/index.html', {'title': 'Home'})
```

### Static Files

Static files are typically the local files that `href`s point to, such as images and JavaScript files. 

Django will look for them in `app/static/app/\*.*`.

Static files are accessed with DTL after loading `static`:

```html
{ % load static % }

<link rel="stylesheet" href="{% static 'blog/main.css' %}">
```

### Databases and Models

Django has its own built-in ORM (Object-Relational Mapper). 

A bonus of this is that it acts as an interface for any database, allowing us to use different DBMS packages. For example, we can use SQLite3 for development and PostgreSQL for production without changing our code.

Our database structure will be represented as classes by the Django ORM. 

These classes are what we’ll use as models. An example blog post model:

```python
class Post(models.Model):
    title = models.CharField(max_length=128)
    date = models.DateTimeField(default=timezone.now)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
```

### Migrations

If you edit the structure of a database through a model, you need to run migrations in order to make the changes to our database.

1. Run `$ python manage.py makemigrations` to create the migrations.
2. Run `$ python manage.py migrate` to run the migrations.

The migrations are stored in your app’s `migrations/` directory (i.e. 0001_initial.py). 

You can open the file to see what it's doing, and even view the SQL query generated from a migration using `$ python manage.py sqlmigrate app 0001`.

---

## Package Management

### Requirements

Instead of manually installing packages, you should keep a text file that lists them. 

Pip can read through this list, and then automatically install these packages in bulk.

`$ pip install -r requirements.txt`.

This has a host of advantages, such as acting as a written record of compatible packages for you and other developers, as well as helping deployment on a new machine.

Django is an obvious necessity. You can list any other useful packages you’d like in there too.

### Virtualenv

You should set up a virtual environment for the project. 

A virtual environment allows us to install packages and versions specifically for a project, rather than globally across our operating system.

- Run `$ pip install virtualenv` if you haven’t already got it installed.
- Enter the root directory of your project, and run `$ python -m venv django-venv`.
- Finally, 'activate' this venv with `$ source django-venv/bin/activate`.

*Windows users need to use `$ source django-venv/Scripts/activate`.*

Now, install your packages into the environment using `$ pip install -r requirements.txt`. 

You'll need to re-enter the environment any time you work on the project.

---

## Extra Bits

### Django Admin

The admin page allows you to manage content on the site through a model-centric interface.

You’ll first need to create some credentials, which requires the default database.

1. Run `$ python manage.py migrate`, which will initialise a default database.
2. Run `$ python manage.py createsuperuser` to set up an admin profile.

Navigate to http://localhost:8000/admin/ again and log-in with your details.

### Django Forms

Django has some built-in form objects for common processes.

The `UserCreationForm` is for registering a new user, and is made up of the `username`, `password1` and `password2` fields. 

Password hashing is built into these form objects.

---

### Final Words

Hopefully this serves as a 5-minute guide, and as a future reference, on the inner workings of Django.

It's important to remember that Django is a fully-fledged framework, and has its nuances and weird bits as much as any language does. You need to start building to get to grips with it!

A great project tutorial can be found at: https://www.youtube.com/watch?v=UmljXZIypDc

Finally, if you have any questions or comments, I may be able to work my replies into this guide to help future readers. Therefore, I welcome all feedback!

Good luck on your development journey.

---