B.
Wakim
Outline
Installing Django Example 3: Blog application
Example 1: infoapp: hello world using models and forms
Creating site and application Create blog application
Migrating data – Running server Create models
Modify settings Register the models
Create a view Migrate data
Create a template Create views
Mapping URL Mapping URL
Example 2: Book application using models Create templates
Create models Create form
Register the models Use the form in the views
Migrate data
function
Access blog site
Create admin user
Retrieving data
Create a template
Mapping URL
Modify views
Django- Creating Simple web sites 2
Installing Django
Create a folder for your projects under python folder. For example:
C:\Users\berna\AppData\Local\Programs\Python\Python39\dprojects
Setting up a virtual environment¶
To create a virtual environment for your project, open a new command prompt,
navigate to the folder where you want to create your project and then enter the
following:
py -m venv C:\Users\berna\AppData\Local\Programs\Python\Python39\dprojects
To activate the environment, run:
C:\Users\berna\AppData\Local\Programs\Python\Python39\dprojects\Scripts\activate.bat
Install django:
pip install django
Check django version: from C:\Users\berna\AppData\Local\Programs\Python\Python39
Python –m django version
N.B: PATH add:
C:\Users\berna\AppData\Local\Programs\Python\Python39\Scripts
Django- Creating Simple web sites 3
Django-admin and manage.py¶
django-admin is Django’s command-line utility for administrative tasks.
In addition, manage.py is automatically created in each Django project. It does
the same thing as django-admin but also sets the
DJANGO_SETTINGS_MODULE environment variable so that it points to your
project’s settings.py file.
The django-admin script should be on your system path if you installed Django
via pip. If it’s not in your path, ensure you have your virtual environment
activated.
Generally, when working on a single Django project, it’s easier to use manage.py
than django-admin. If you need to switch between multiple Django settings
files, use django-admin with DJANGO_SETTINGS_MODULE or the --settings
command line option.
Usage¶
manage.py <command> [options] oR
django-admin <command> [options] OR
python -m django <command> [options]
Django- Creating Simple web sites 4
Django- Creating Simple web sites 5
Creating site and application
Create your own site:
cd dprojects
django-admin startproject infosite
infosite/ #outer site
manage.py
infosite/ #inner site
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
Create your own application:
cd infosite #outer site, containing manage.py
python -m django startapp infoapp OR django-admin startapp infoapp
Django- Creating Simple web sites 6
Migrating data – Running server
Migrating data for existing apps:
cd infosite
manage.py migrate
Running the server:
manage.py runserver
Open a web browser and call:
http://localhost:8000/
Django- Creating Simple web sites 7
Modify settings.py
Edit infosite/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'infoapp.apps.InfoappConfig'
]
Django- Creating Simple web sites 8
Create a view
Under infoapp, Edit the file views.py (using IDLE): and type:
from django.shortcuts import render
def index(request):
return render(request, 'hello_world.html', {})
The view function takes one argument, request. This object is an
HttpRequestObject that is created whenever a page is loaded. It
contains information about the request, such as the method, which
can take several values including GET and POST.
Django- Creating Simple web sites 9
Create a template
Now that you’ve created the view function, you need to create the
HTML template to display to the user.
render() looks for HTML templates inside a directory called templates
inside your app directory. Create that directory and subsequently a file
named hello_world.html inside it (using notepad):
<h1>Hello, World!</h1>
You’ve now created a function to handle your views and templates to
display to the user.
The final step is to hook up your URLs so that you can visit the page
you’ve just created.
Django- Creating Simple web sites 10
Mapping URL
Your project has a module called urls.py in which you need to include a
URL configuration for the infoapp.
Inside infosite/urls.py, add the following:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(‘infoapp.urls')),
]
This looks for a module called urls.py inside the infoapp application
and registers any URLs defined there.
Whenever you visit the root path of your URL (localhost:8000), the
infoapp application’s URLs will be registered.
Django- Creating Simple web sites 11
Mapping URL
The infoapp.urls module doesn’t exist yet, so you’ll need to create it:
Inside this module, we need to import the path object as well as our
app’s views module.
Then we want to create a list of URL patterns that correspond to the
various view functions.
At the moment, we have only created one view function, so we need
only create one URL:
from django.urls import path
from infoapp import views
urlpatterns = [
path('',views.index, name='index'),
]
Django- Creating Simple web sites 12
Django- Creating Simple web sites 13
Create models.py
from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=100)
publication_date = models.DateField()
def __unicode__(self):
return self.title
Django- Creating Simple web sites 14
Register the models
Infoapp/admins.py
from django.contrib import admin
# Register your models here.
from infoapp.models import Book
admin.site.register(Book)
Django- Creating Simple web sites 15
Migrate data
We are in infosite folder (outer) containing manage.py.
Create migrations for new model:
manage.py makemigrations
➔ Migrations for 'infoapp': infoapp\migrations\0001_initial.py
- Create model Book
Migrations done are stored in infoapp\migrations\0001_initial.py
Apply these migrations:
manage.py migrate infoapp 0001
➔ Operations to perform: Target specific migration: 0001_initial, from
infoapp
Running migrations: Applying infoapp.0001_initial... OK
Migrate all the application:
manage.py migrate infoapp
➔ Operations to perform: Apply all migrations: infoapp
Running migrations: No migrations to apply.
Django- Creating Simple web sites 16
Create admin user
We are in infosite folder (outer) containing manage.py.
Create admin user for the DB:
manage.py createsuperuser --username info
You have to enter an email and a password.
(info/I409409!)
Run the server:
manage.py runserver
Go to the admin page to login:
http://localhost:8000/admin
Click on book and add data.
Django- Creating Simple web sites 17
Retrieving data
Modify views.py to add the retrieve book_by_id function:
from django.shortcuts import render
from django.http import HttpResponse
from infoapp.models import Book
# Create your views here.
def index(request):
return render(request, 'hello_world.html', {})
def book_by_id(request, book_id):
book=Book.objects.get(pk=book_id)
return HttpResponse(f"Book title: {book.title}, published: {book.publication_date}")
Django- Creating Simple web sites 18
Mapping urls
Modify urls.py to add a map to the retrieve book function:
from django.urls import path
from infoapp import views
urlpatterns = [
path('',views.index, name='index'),
path('book/<int:book_id>',views.book_by_id, name='book_by_id'),
]
Test the function:
http://localhost:8000/book/3
➔ Book title: Book3, published: 2021-03-01
Django- Creating Simple web sites 19
Create a template – Modify views
In infoapp/templates, create a template named book_details.html containing:
<p> Title: {{ book.title }} </p>
<p> pub_date: {{ book.publication_date }} </p>
Modify infoapp/views.py, to use the created template:
def book_by_id(request, book_id):
book=Book.objects.get(pk=book_id)
return render(request,'book_details.html',{‘book':book})
Test the function with the template
http://localhost:8000/book/3
➔
Title: Book3
pub_date: March 1, 2021
Django- Creating Simple web sites 20
Django- Creating Simple web sites 21
Create Blog application
In this example, you’re going to build a fully functioning blog that will allow
you to perform the following tasks:
Create, update, and delete blog posts
Display posts to the user as either an index view or a detail view
Assign categories to posts
Allow users to comment on posts
First create a new Django app named blog.
manage.py startapp blog
Modify settings.py
INSTALLED_APPS = [
“……
“infoapp",
"blog",
]
Django- Creating Simple web sites 22
Create blog/models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=20)
class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField('Category', related_name='posts‘)
class Comment(models.Model):
author = models.CharField(max_length=60)
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey('Post', on_delete=models.CASCADE)
Django- Creating Simple web sites 23
Migrate data
Once you’ve created the models, you can create the
migration files with makemigrations:
manage.py makemigrations blog
The final step is to migrate the tables:
manage.py migrate
Register the models in admin.py
Run server
manage.py runserver
Add data
Django- Creating Simple web sites 24
Register the models
In the blog directory, open the file admin.py and type the
following lines of code:
from django.contrib import admin
from blog.models import Post, Category
admin.site.register(Post)
admin.site.register(Category)
admin.site.register(Comment)
Django- Creating Simple web sites 25
Create views
You’ll need to create three view functions in the
views.py file in the blog directory:
blog_index will display a list of all your posts.
blog_detail will display the full post as well as comments
and a form to allow users to create new comments.
blog_category will be similar to blog_index, but the
posts viewed will only be of a specific category chosen by
the user
Django- Creating Simple web sites 26
Blog_index function
Import the Post and the Comment models
Inside the view function, you obtain a Queryset containing all the posts in the database.
order_by() The minus sign tells Django to start with the largest value rather than the
smallest. We use this, as we want the posts to be ordered with the most recent post first.
Finally, you define the context dictionary and render the template.
def blog_index(request):
posts = Post.objects.all().order_by('-created_on')
context = {
"posts": posts,
}
return render(request, "blog_index.html", context)
Context is a dictionary with variable names as the key and their values as the value.
Hence, if your context for the above template looks like: {myvar1: 101, myvar2: 102} , when
you pass this context to the template render method, {{ myvar1 }} would be replaced with
101 and {{ myvar2 }} with 102 in your template.
Django- Creating Simple web sites 27
Blog_category function
In this case, we filter posts whose categories contain the category with the
name corresponding to that given in the argument of the view function.
Again, you’re using order_by() to order posts starting with the most recent.
We then add these posts and the category to the context dictionary, and render
our template.
def blog_category(request, category):
posts = Post.objects.filter(
categories__name__contains=category
).order_by(
'-created_on'
)
context = {
"category": category,
"posts": posts
}
return render(request, "blog_category.html", context)
Django- Creating Simple web sites 28
Blog_detail function
The view function takes a pk value as an argument and retrieves the object with
the given pk.
We retrieve all the comments assigned to the given post using Django filters
again.
Lastly, add both post and comments to the context dictionary and render the
template.
def blog_detail(request, pk):
post = Post.objects.get(pk=pk)
comments = Comment.objects.filter(post=post)
context = {
"post": post,
"comments": comments,
}
return render(request, "blog_detail.html", context)
Django- Creating Simple web sites 29
With this set up, all the blog URLs will be prefixed with
Mapping urls blog/, and you’ll have the following URL paths:
• localhost:8000/blog: Blog index
• localhost:8000/blog/1: Blog detail view of blog with pk=1
Adding blog/urls • localhost:8000/blog/cat4: Blog index view of all posts
from django.urls import path with category cat4
from blog import views
urlpatterns = [
path("", views.blog_index, name="blog_index"),
path("<int:pk>/", views.blog_detail, name="blog_detail"),
path("<category>/", views.blog_category, name="blog_category"),
]
Add urls to the infosite URL configuration using include():
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path(“infoapp/", include(“infoapp.urls")),
path("blog/", include("blog.urls")),
]
Django- Creating Simple web sites 30
Common site templates
If we want our entire site to look consistent on the front end, we can create a template or
set of templates that are shared by all the apps.
Create infosite/templates/base.html:
{% block page_content %}{% endblock %}
Then we can extend this html file in every template:
{% extends "base.html" %}
We need to tell our Django project that base.html exists. The default settings register
template directories in each app, but not in the project/site directory itself.
In infosite/settings.py, update TEMPLATES:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [“infosite/templates/"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
………
]
},
}
]
Django- Creating Simple web sites 31
Create blog_index.html template
{% extends "base.html" %} You’ll use a for loop to loop
{% block page_content %} over all the posts. For each
<div class="col-md-8 offset-md-2"> post, you’ll display the title
and a snippet of the body.
<h1>Blog Index</h1>
We have the post title, which
<hr> is a hyperlink. The link is a
{% for post in posts %} Django link where we are
<h2><a href="{% url 'blog_detail' post.pk%}">{{ post.title }}</a></h2> pointing to the URL named
<small> blog_detail, which takes an
{{ post.created_on.date }} | integer as its argument and
should correspond to the pk
Categories: value of the post.
{% for category in post.categories.all %} Underneath the title, we’ll
<a href="{% url 'blog_category' category.name %}"> display the created_on
{{ category.name }} attribute of the post as well as
</a> its categories. We use another
{% endfor %} for loop to loop over all the
categories assigned to the
</small> post.
<p>{{ post.body | slice:":400" }}...</p> We use a template filter slice
{% endfor %} to cut off the post body at 400
</div> characters so that the blog
{% endblock %} index is more readable.
Django- Creating Simple web sites 32
Adding blog_category.html template
{% extends "base.html" %} This should be identical
{% block page_content %} to blog_index.html,
<div class="col-md-8 offset-md-2"> except with the
<h1>{{ category | title }}</h1>
category name inside
<hr>
the h1 tag.
{% for post in posts %}
<h2><a href="{% url 'blog_detail' post.pk%}">{{ post.title The only difference is
}}</a></h2> where we use another
<small> Django template filter
{{ post.created_on.date }} | title. This applies title
Categories: case to the string and
{% for category in post.categories.all %} makes words start with
<a href="{% url 'blog_category' category.name %}">
an uppercase character.
{{ category.name }}
</a>
{% endfor %}
</small>
<p>{{ post.body | slice:":400" }}...</p>
{% endfor %}
</div>
{% endblock %}
Django- Creating Simple web sites 33
Create blog_detail.html template
{% extends "base.html" %} The first few lines of
{% block page_content %} the template in which
<div class="col-md-8 offset-md-2"> we display the post
title, date, and
<h1>{{ post.title }}</h1>
categories is the same
<small> logic as for the previous
{{ post.created_on.date }} | templates.
Categories: This time, when
{% for category in post.categories.all %} rendering the post
<a href="{% url 'blog_category' category.name %}"> body, use a linebreaks
template filter. This tag
{{ category.name }}
registers line breaks as
</a> new paragraphs, so the
{% endfor %} body doesn’t appear as
</small> one long block of text.
<p>{{ post.body | linebreaks }}</p>
Django- Creating Simple web sites 34
Create blog_detail.html template
<h3>Leave a comment:</h3>
<form action="/blog/{{ post.pk }}/" method="post">
{% csrf_token %}
<div class="form-group">
{{ form.author }}
</div>
<div class="form-group">
{{ form.body }}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<h3>Comments:</h3>
{% for comment in comments %}
<p>
On {{comment.created_on.date }}
<b>{{ comment.author }}</b> wrote:
</p>
<p>{{ comment.body }}</p>
<hr>
{% endfor %}
</div>
{% endblock %}
Django- Creating Simple web sites 35
Create blog_detail.html template
Underneath the post you’ll display your form. The form action points to
the URL path of the page to which you’re sending the POST request to.
In this case, it’s the same as the page that is currently being visited.
You then add a csrf_token, which provides security and renders the
body and author fields of the form, followed by a submit button.
Underneath the form, there’s another for loop that loops over all the
comments on the given post. The comments, body, author, and
created_on attributes are all displayed.
csrf_token. Django has a {% csrf_token %} tag that is implemented
to avoid malicious attacks. It generates a token on the server-side
when rendering the page and makes sure to cross-check this token for
any requests coming back in. If the incoming requests do not contain
the token, they are not executed.
Django- Creating Simple web sites 36
Create a form
To add a form to the page, you’ll need to create another file in the blog
directory named forms.py.
Django forms are very similar to models. A form consists of a class
where the class attributes are form fields. Django comes with some
built-in form fields that you can use to quickly create the form you
need.
For this form, the only fields you’ll need are author, which should be a
CharField, and body, which can also be a CharField.
Note: If the CharField of your form corresponds to a model CharField,
make sure both have the same max_length value.
Django- Creating Simple web sites 37
Create a form
Adding blog/forms.py You’ll also notice an argument
from django import forms widget has been passed to both the
fields:
class CommentForm(forms.Form): The author field has the
forms.TextInput widget. This tells
author = forms.CharField( Django to load this field as an
max_length=60, HTML text input element in the
widget=forms.TextInput(attrs={ templates.
"class": "form-control", The body field uses a
forms.TextArea widget instead, so
"placeholder": "Your Name"
that the field is rendered as an
}) HTML text area element.
)
body = forms.CharField(widget=forms.Textarea( These widgets also take an
attrs={ argument attrs, which is a
"class": "form-control", dictionary and allows us to specify
"placeholder": "Leave a comment!" some CSS classes, which will help
}) with formatting the template for
) this view later. It also allows us to
add some placeholder text.
Django- Creating Simple web sites 38
Use a form in the blog_detail function
from blog.forms import CommentForm When a form is posted, a POST
def blog_detail(request, pk): request is sent to the server. So, in the
post = Post.objects.get(pk=pk) view function, we need to check if a
POST request has been received, we
form = CommentForm() #instance of the form class can then create a comment from the
if request.method == 'POST': form fields.
form = CommentForm(request.POST) Django comes with a handy is_valid()
if form.is_valid(): on its forms, so we can check that all
comment = Comment( the fields have been entered correctly.
author=form.cleaned_data["author"], We check if a POST request has been
body=form.cleaned_data["body"], received. If it has, then we create a
post=post new instance of our form, populated
) with the data entered into the form.
comment.save() Once you’ve created the comment
from the form, you’ll need to save it
comments = Comment.objects.filter(post=post) using save().
context = { Then query the database for all the
comments assigned to the given post.
"post": post,
Save the comment and go on to add
"comments": comments,
the form to the context dictionary so
"form": form,
you can access the form in the HTML
}
template.
return render(request, "blog_detail.html", context)
Django- Creating Simple web sites 39
Access blog site
To access blog_index:
http://localhost:8000/blog/
To access your category view and see all the posts with
that category:
http://localhost:8000/blog/cat4
To access your blog detail with pk=1:
localhost:8000/blog/1
N.B: you can change infoapp/views to associate hello to name=index
Django- Creating Simple web sites 40