Creating a simple app
Assignment 5 is due tomorrow.
What happens when you do this?
$> pip install Django
import django
django.VERSION # gives you 4.0.4
django-admin
is installed in your environment.It's Django’s command-line utility for administrative tasks. It can:
Let's create a new project so that users can browse this painstakingly curated collection of information about cheeses and rate cheeses they have tried.
$> django-admin startproject cheeseshop
Run this command in the directory where you want to create your Django project.
Generally it's a good idea to run it in the root directory of a Github project you want to keep your site in.
What did startproject
do?
cheeseshop/ manage.py cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py
It created some files.
What is manage.py
for?
cheeseshop/ manage.py cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py
django-admin
; it does all the same things but specific to your project.django-admin
and start using manage.py
to do things.manage.py
.Let's use this utility to start up a Django webserver:
$> python manage.py runserver
This will start up a small, simple webserver you can use for local development. You can visit your website at http://127.0.0.1:8000/
What is 127.0.0.1
, aka localhost
?
Let's look at our files again:
cheeseshop/ manage.py db.sqlite3 cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py
Wait, where did this db.sqlite3
come from? It wasn't there before.
What is settings.py
for?
cheeseshop/ manage.py db.sqlite3 cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py
What is urls.py
for?
cheeseshop/ manage.py db.sqlite3 cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py
What about asgi.py
and wsgi.py
?
cheeseshop/ manage.py db.sqlite3 cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py
WSGI stands for Web Server Gateway Interface. It is a specification that describes how a web server communicates with Python web applications.
So far we've used the Django development web server, but if you were to deploy your app in production, you would use a real server.
This server would communicate without our Django app via WSGI, and use the wsgi.py
file to do it.
Let's create a view to replace the default Django one.
cheeseshop/ manage.py db.sqlite3 cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py views.py
cheeseshop/views.py
from datetime import datetime
from django.http import HttpResponse
def index(request):
now = datetime.now()
return HttpResponse(f"It is now {now}.")
cheeseshop/urls.py
from django.contrib import admin
from django.urls import path
from cheeseshop.views import index
urlpatterns = [
path("", index),
]
Note that we didn't have to do anything ohter than go to our browser and reload the page.
The Django webserver restarts whenever it sees your Python code has changed.
This is pretty boring. Can we spice it up a bit? Maybe add some HTML?
Create a folder in the Django project root called "templates".
index.html
inside that.cheeseshop/ manage.py db.sqlite3 cheeseshop/ __init__.py settings.py urls.py asgi.py wsgi.py views.py templates/ index.html
cheeseshop/views.py
from datetime import datetime
from django.shortcuts import render
def index(request):
now = datetime.now()
return render(request, "index.html", {"now": now})
Templates are rendered with a context.
A context is a list of variables that will be available in a template. It's represented as a dictionary where the keys are the variable names and the values are the variable values.
{
"date": datetime.now(),
"name": "Bob Smith",
"age": 28
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cheese Shop</title>
</head>
<body>
<h1>Cheese Shop</h1>
<p>Welcome!</p>
<p>Today is: {{ now }} </p>
</body>
</html>
So far we've...
cheeseshop/views.py
cheeseshop/urls.py
templates/index.html
Explicit is better than implicit.
We forgot a step
cheeseshop/views.py
cheeseshop/urls.py
templates/index.html
cheeseshop/settings.py
(partial)
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',
],
},
},
]
cheeseshop/settings.py
(partial)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['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',
],
},
},
]