Chapter 18: Getting Started with Django
Django is a full-featured web framework. Build data-driven web apps efficiently.
Project: Server Inventory
A web app to track infrastructure. Users register servers and log events.
Setting Up Django
Virtual Environment
mkdir server_inventory && cd server_inventory
python -m venv .venv
source .venv/bin/activate
Installing Django
pip install django
Creating the Project
django-admin startproject inv_project .
Project structure:
server_inventory/ ├── .venv/ ├── inv_project/ │ ├── __init__.py │ ├── settings.py # Project configuration │ ├── urls.py # URL routing │ ├── asgi.py │ └── wsgi.py └── manage.py # Django commands
Creating an App
python manage.py startapp inventory
App structure:
inventory/ ├── __init__.py ├── admin.py # Admin site config ├── apps.py # App config ├── models.py # Data models ├── tests.py # Tests └── views.py # Request handlers
Register the App
# inv_project/settings.py
INSTALLED_APPS = [
# My apps
'inventory',
# Default Django apps
'django.contrib.admin',
'django.contrib.auth',
# ...
]
Defining Models
Models define data structure. Django creates database tables.
# inventory/models.py
from django.db import models
class Server(models.Model):
"""A server in the infrastructure."""
hostname = models.CharField(max_length=100)
ip_address = models.GenericIPAddressField()
os = models.CharField(max_length=50, default='linux')
status = models.CharField(max_length=20, default='active')
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.hostname} ({self.ip_address})"
class Event(models.Model):
"""An event logged for a server."""
server = models.ForeignKey(Server, on_delete=models.CASCADE) (1)
timestamp = models.DateTimeField(auto_now_add=True)
event_type = models.CharField(max_length=20) # deploy, restart, alert
message = models.TextField()
class Meta:
ordering = ['-timestamp'] (2)
def __str__(self):
return f"{self.server.hostname}: {self.event_type} - {self.message[:50]}"
| 1 | Link to Server; delete events when server deleted |
| 2 | Most recent first |
Migrations
Track model changes:
python manage.py makemigrations inventory
python manage.py migrate
After any model change, run both commands.
Django Admin Site
Registering Models
# inventory/admin.py
from django.contrib import admin
from .models import Server, Event
admin.site.register(Server)
admin.site.register(Event)
Visit 127.0.0.1:8000/admin/ to manage data.
Django Shell
Interact with models:
python manage.py shell
>>> from inventory.models import Server, Event
>>> Server.objects.all()
<QuerySet []>
>>> s = Server(hostname='web-01', ip_address='10.0.1.10')
>>> s.save()
>>> Server.objects.all()
<QuerySet [<Server: web-01 (10.0.1.10)>]>
>>> s.event_set.create(event_type='deploy', message='Initial deployment')
<Event: web-01: deploy - Initial deployment>
>>> s.event_set.all()
<QuerySet [<Event: web-01: deploy - Initial deployment>]>
Building Pages
Three components: 1. URL - Maps URL pattern to view 2. View - Processes request, returns response 3. Template - HTML with dynamic content
Project URLs
# inv_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('inventory.urls')),
]
App URLs
# inventory/urls.py
from django.urls import path
from . import views
app_name = 'inventory'
urlpatterns = [
path('', views.index, name='index'),
path('servers/', views.servers, name='servers'),
path('servers/<int:server_id>/', views.server_detail, name='server_detail'),
]
Views
# inventory/views.py
from django.shortcuts import render
from .models import Server
def index(request):
"""Dashboard home."""
return render(request, 'inventory/index.html')
def servers(request):
"""List all servers."""
servers = Server.objects.order_by('hostname')
context = {'servers': servers}
return render(request, 'inventory/servers.html', context)
def server_detail(request, server_id):
"""Show server details and events."""
server = Server.objects.get(id=server_id)
events = server.event_set.all()
context = {'server': server, 'events': events}
return render(request, 'inventory/server_detail.html', context)
Templates
Create directory: inventory/templates/inventory/
<!-- inventory/templates/inventory/base.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Server Inventory</title>
</head>
<body>
<nav>
<a href="{% url 'inventory:index' %}">Dashboard</a>
<a href="{% url 'inventory:servers' %}">Servers</a>
</nav>
{% block content %}{% endblock content %}
</body>
</html>
<!-- inventory/templates/inventory/index.html -->
{% extends 'inventory/base.html' %}
{% block content %}
<h1>Infrastructure Dashboard</h1>
<p>Track servers, log events, monitor your infrastructure.</p>
{% endblock content %}
<!-- inventory/templates/inventory/servers.html -->
{% extends 'inventory/base.html' %}
{% block content %}
<h1>Servers</h1>
<table>
<tr>
<th>Hostname</th>
<th>IP</th>
<th>OS</th>
<th>Status</th>
</tr>
{% for server in servers %}
<tr>
<td>
<a href="{% url 'inventory:server_detail' server.id %}">
{{ server.hostname }}
</a>
</td>
<td>{{ server.ip_address }}</td>
<td>{{ server.os }}</td>
<td>{{ server.status }}</td>
</tr>
{% empty %}
<tr><td colspan="4">No servers registered.</td></tr>
{% endfor %}
</table>
{% endblock content %}
<!-- inventory/templates/inventory/server_detail.html -->
{% extends 'inventory/base.html' %}
{% block content %}
<h1>{{ server.hostname }}</h1>
<p>IP: {{ server.ip_address }} | OS: {{ server.os }} | Status: {{ server.status }}</p>
<h2>Events</h2>
<ul>
{% for event in events %}
<li>
<strong>{{ event.timestamp|date:'Y-m-d H:i' }}</strong>
[{{ event.event_type }}] {{ event.message }}
</li>
{% empty %}
<li>No events logged.</li>
{% endfor %}
</ul>
{% endblock content %}
Quick Reference
| Command | Purpose |
|---|---|
|
Create project |
|
Create app |
|
Create migrations |
|
Apply migrations |
|
Create admin user |
|
Start dev server |
|
Django shell |
| Template Tag | Purpose |
|---|---|
|
Inherit from template |
|
Define/override section |
|
Generate URL |
|
Loop |
|
Conditional |
|
Output value |
|
Apply filter |
Exercises
18-1. Service Model
Add a Service model (name, port, protocol, server FK). Display services on server detail.
18-2. Status Choices
Use Django’s choices parameter to limit status to: active, maintenance, decommissioned.
18-3. Shell Practice
Create 3 servers and 5 events via Django shell.
18-4. Search
Add a search box to filter servers by hostname.
Summary
-
Django projects contain apps with specific functionality
-
Models define data structure; migrations sync database
-
Admin site provides data management interface
-
URLs map patterns to views
-
Views process requests and return responses
-
Templates render HTML with dynamic content
-
{% extends %}enables template inheritance
Next: User input with forms.