Django
django_project.zip |
to install Django run:
pip install Django
or to check if you already have one installed:
python -m django --version
the way Django works is somewhat similar to SprigBoot, where it does some initial set up for you.
To start a project run
pip install Django
or to check if you already have one installed:
python -m django --version
the way Django works is somewhat similar to SprigBoot, where it does some initial set up for you.
To start a project run
$ django-admin startproject django_project
this should create a folder named django_project in the current directory
└──django_project outer project folder, the name is not important ├──manage.py command line utility for admin tasks └── django_project application package, this name matters ├──settings.py configurations for your project ├──asgi.py base ASGI server ├──urls.py application routes ├──wsgi.py base WSGI server └──__init__.py truns a folder into a package, may have some specifications
to see if the initial configuration worked successfully, cd into the top-level folder and run the server:
$ cd django_project/ $ python manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). 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. November 07, 2020 - 11:30:45 Django version 3.1.2, using settings 'django_project.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. [07/Nov/2020 11:30:56] "GET / HTTP/1.1" 200 16351 [07/Nov/2020 11:30:56] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423 [07/Nov/2020 11:30:56] "GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1" 200 85876 [07/Nov/2020 11:30:56] "GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1" 200 86184 [07/Nov/2020 11:30:56] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 200 85692 Not Found: /favicon.ico [07/Nov/2020 11:30:56] "GET /favicon.ico HTTP/1.1" 404 1980
We will create our own new view and a route first
I created a new folder, called hello_world in the root of the outer folder, and this is the file structure I have now:
I created a new folder, called hello_world in the root of the outer folder, and this is the file structure I have now:
└──django_project ├──manage.py ├──django_project └──hello_world ├──urls.py ├──views.py └──__init__.py
views.py
from django.http import HttpResponse def index(request): return HttpResponse("Hello, world!")
urls.py
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
Modify django_project/urls.py to redirect to the hello_world urls:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('hello/', include('hello_world.urls')), path('admin/', admin.site.urls), ]
we now can re-launch the server and the new route/view should be accessible:
$ python manage.py runserver
Rendering Templates:
in the hello_world subfolder, create another subfolder, called templates and place hello_world.html in it, like so:
└──hello_world ├──urls.py ├──views.py ├──__init__.py └──templates └──hello_world.html
hello_world.html
<h1>Hello, World!</h1>
add another endpoint in
views.py
from django.http import HttpResponse from django.shortcuts import render def index(request): return HttpResponse("Hello, world!") def hello_world(request): return render(request, 'hello_world.html', {})
and add the URL pattern in the urls.py
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('hello_world', views.hello_world, name='hello_world') ]
modify the settings.py under main project folder to know where to locate the templates
SETTINGS_PATH = os.path.dirname(os.path.dirname(__file__)) TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(SETTINGS_PATH, 'hello_world','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', ], }, },
Creating a Model:
We will create a database of people registered to vote.
First we need to create the model:
in the hello_world folder add new file models.py
from django.db import models class Person(models.Model): fname = models.CharField(max_length=50) lname = models.CharField(max_length=50) age = models.IntegerField(default=18)
Modify settings.py in the django_project to include the new hello_world app created:
INSTALLED_APPS = [ 'hello_world', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
Now run makemigrations:
python manage.py makemigrations hello_world
and Migrate:
python manage.py sqlmigrate hello_world 0001
python manage.py migrate
This extends the database used by django and adds a hello_world_person table
We will now create a page for the users to register to vote and another page to respond back to the user as they register.
We will add 2 new URLs in the hello_world/urls.py page
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('hello_world', views.hello_world, name='hello_world'), path('register', views.register, name='register'), path('registered', views.registered, name='registered') ]
And add their implementation in the hello_world/views.py
from django.http import HttpResponse from django.shortcuts import render from .models import Person def index(request): return HttpResponse("Hello, world!") def hello_world(request): return render(request, 'hello_world.html', {}) def register(request): return render(request, 'register.html', {}) def registered(request): first_name = request.GET['first_name'] last_name = request.GET['last_name'] age = request.GET['age'] context={"first_name":first_name, "last_name":last_name, "age":age} return render(request, 'registered.html', context)
a register.html template in the hello_world/templates/
<h1>Register to Vote</h1> <form action="registered"> First Name: <input type="text" name="first_name"><br><br> Last Name: <input type="text" name="last_name"><br><br> Age: <input type="text" name = "age"><br><br> <input type="submit" value="Submit"> </form>
and a registered.html in the hello_world/templates/
<h1>{{first_name}} {{last_name}} you have successfully registered</h1>
Now you can run the app using
$ python managpy runserver
We did the exercise above to learn how to work with GET parameters, but now we will change them to more meaningful POST parameters and some additional functionality django provides
We are going to create a form.py and place it in the hello_world directory:
from django import forms from .models import Person class PersonForm(forms.ModelForm): class Meta: model = Person fields = ['fname', 'lname', 'age'] #fields = '__all__' will set all model fields
We then modify the few and create that form in the register section and pass it to the template:
cleaned_data explained
from django.http import HttpResponse from django.shortcuts import render from .models import Person from .forms import PersonForm def index(request): return HttpResponse("Hello, world!") def hello_world(request): return render(request, 'hello_world.html', {}) def register(request): return render(request, 'register.html', {"form":PersonForm()}) def registered(request): form = PersonForm(request.POST) if form.is_valid(): form.save() print(form) context = { 'fname':form.cleaned_data['fname'], 'lname':form.cleaned_data['lname'] } return render(request, 'registered.html', context)
The register.html template is now modified to use the form instead of the explicit HTML input fields:
<h1>Register to Vote</h1> <form action="registered" method = "POST"> <table>{{ form }}</table> <input type="submit" value="Register" /> {% csrf_token %} </form>
registered.html
<h1>{{fname}} {{lname}} you have successfully registered</h1>
We will now add an endpoint for listing all the registered voters in the database
add new endpoint in the urls.py
add new endpoint in the urls.py
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('hello_world', views.hello_world, name='hello_world'), path('register', views.register, name='register'), path('registered', views.registered, name='registered'), path('all', views.listall, name='listall') ]
Additional endpoint in views.py
from django.http import HttpResponse from django.shortcuts import render from .models import Person from .forms import PersonForm def index(request): return HttpResponse("Hello, world!") def hello_world(request): return render(request, 'hello_world.html', {}) def register(request): return render(request, 'register.html', {"form":PersonForm()}) def registered(request): form = PersonForm(request.POST) if form.is_valid(): form.save() print(form) context = { 'fname':form.cleaned_data['fname'], 'lname':form.cleaned_data['lname'] } return render(request, 'registered.html', context) def listall(request): all_entries = Person.objects.all() return render(request, 'listall.html', {"persons":all_entries})
and the listall.html:
<table width="80%"> <tr> <td>First</td> <td>Last</td> <td>Age</td> </tr> {%for p in persons%} <tr> <td>{{p.fname}}</td> <td>{{p.lname}}</td> <td>{{p.age}}</td> </tr> {%endfor%} </table>
Additional Resources: