Learning log
Here we will see some more advanced features like admin account and databases.
Creating a Project in Django:
django-admin.py startproject learning_log .
Our project is called learning_log
.
Creating a database for the project:
python3 manage.py migrate
Now you will see a new file called db.sqlite3
in the directory.
Viewing the Project:
python3 manage.py runserver
You can visit localhost:8000
in your browser, and you should see a default
django webpage. Django project is consists of a set of individual apps. This
modular approach helps to organize complex apps. In order to start an app:
python3 manage.py startapp learning_log_app
We call our app learning_log_app
. Check all the directory structure.
Creating models
Open learning_log_app/models.py
and define a model:
class Topic(models.Model):
"""A topic the user is learning"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string representation of the model"""
return self.text
We can build as many models we want. We can define it by our requirements. Here
we are defining our Topic model based on the Django in-built models.Model
.
Activating models
Once we have defined a model in our app, we have to include in our global django
settings. Open learning_log/settings.py
add learning_log_app
app to the list
of INSTALLED_APPS
list:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# My apps
'learning_log_app',
]
Make the migration to take changes effect:
python3 manage.py makemigrations learning_log_app
python3 manage.py migrate
Create superuser
python3 manage.py createsuperuser
Provide username and password.
Registering a model with the admin site: Open learning_log_app/admin.py
and
add the following:
from learning_log_app.models import Topic
admin.site.register(Topic)
Now we can start the server python3 manage.py runserver
and login to
localhost:8000/admin
and create Topics.
Let's define another model for the Entry. Open learning_log_app/models.py
and
define a model for Entry.
class Entry(models.Model):
"""Something specific learned about a topic"""
topic = models.ForeignKey(Topic, on_delete=models.DO_NOTHING,)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Return a string representation of the model."""
return self.text[:50] + "..."
Make changes to the learning_log_app/admin.py
:
from django.contrib import admin
from learning_log_app.models import Topic
from learning_log_app.models import Entry
admin.site.register(Topic)
admin.site.register(Entry)
Make migrations:
python3 manage.py makemigrations learning_log_app
python3 manage.py migrate
You can start server and check out the new changes.
Creating pages
Creating pages has three steps: (1) Mapping URL, (2) Writing views, (3) Writing templates.
Mapping URL: You have tell Django, what to look for when a url is requested.
Open learning_log/urls.py
and include the following. You will see that the
admin/
path is already registered when we created the admin account. Now we
are including our home page (base url) will look for the urls in the
learning_log_app app urls.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('learning_log_app.urls'))
]
Create an urls.py in the directory learning_log_app and include the following:
"""This file includes the urls of our learning_log_app """
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
Writing view: A view function takes the request and prepares a webpage to
render. Open learning_log_app/views.py
and add the following:
from django.shortcuts import render
def index(request):
"""The home page for Learning Log"""
return render(request, 'learning_log_app/index.html')
Writing a template: We will store the templates in the following directory:
learning_log_app/templates/learning_log_app
. Create an
learning_log_app/templates/learning_log_app/index.html
:
<html>
<head>
<title>Learning log homepage</title>
</head>
<body>
<h3>Welcome to learning Log</h3>
<p>Here you can keep track of the topics you are learning.</p>
</body>
</html>
Note that in the above code block there is an extra space in head
tags, please
remove the spaces in your actual code (my website search function has some
issues with the head
tag, and I am using this workaround to counter the error
currently). We can browse the homepage localhost:8000
and see the index page.
Now that we know how to build a basic page, we will follow the same process to build a page to list our topics and another to show the entries for each topic.
Creating templates
In almost all web project you will find, there are some contents that are shared
by several other pages. Instead of hard coding those common elements, we can
build templates. Let's create a template base.html
where we will include the
title of the pages. Create a file
learning_log_app/templates/learning_log_app/base.html
and include our title
html:
<html>
<head>
<title>Learning log</title>
</head>
<body>
<h3><a href="{% url 'index' %}">Learning log</a></h3>
{% block content %}{% endblock content %}
</body>
</html>
Now we will use this template to build other pages. Let's rewrite our
learning_log_app/templates/learning_log_app/index.html
using this template:
{% extends "learning_log_app/base.html" %}
{% block content %}
<p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>
{% endblock content %}
Let's create our Topics page. Register the url pattern in
learning_log_app/urls.py
:
urlpatterns = [
url('', views.index, name='index'),
# Show all topics
url('topics/', views.topics, name='topics'),
]
Register the views in learning_log_app/view.py
:
from learning_log_app.models import Topic
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_log_app/topics.html', context)
Create learning_log_app/templates/learning_log_app/topics.html
{% extends "learning_log_app/base.html" %}
{% block content %}
<h3>List of topics</h3>
<ul>
{% for topic in topics %}
<li>{{ topic }}</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}
Now let's add individual topics pages. Update the url pattern
learning_log_app/urls.py
:
path('topics/(<int:topic_id>/', views.topic, name='topic'),
Update the views learning_log_app/views.py
:
def
def topic(request, topic_id):
"""Show a single topic and all its entries."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_log_app/topic.html', context)
Create a new learning_log_app/templates/learning_log_app/topic.html
:
{% extends 'learning_log_app /base.html' %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p> <p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>
<p>There are no entries for this topic yet.</p>
</li>
{% endfor %}
</ul>
{% endblock content %}
Link the specific topic pages in our
learning_log_app/templates/learning_log_app/topics.html
:
<li>
<a href="{% url 'topic' topic.id %}">({{ topic.id }}) {{ topic }}</a>
</li>
Working in Djngo shell:
python3 manage.py shell
Allow users to create entries
We can let users submit and edit topics and entries via ModelForm
. Create a
forms file learning_log_app/forms.py
:
from django import forms
from .models import Topic
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
URL for new Topics page: Add following to our learning_log_app/urls.py
:
path('new_topic/', views.new_topic, name='new_topic'),
Update new_topic() in learning_log_app/views.py
:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from learning_log_app.models import Topic
from learning_log_app.forms import TopicForm
def index(request):
"""The home page for Learning Log"""
return render(request, 'learning_log_app/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_log_app/topics.html', context)
def topic(request, topic_id):
"""Show a single topic and all its entries."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_log_app/topic.html', context)
def new_topic(request):
"""Add a new topic."""
if request.method != 'POST':
# No data submitted; create a blank form.
form = TopicForm()
else:
# POST data submitted; process data.
form = TopicForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('learning_log_app:topics'))
context = {'form': form}
return render(request, 'learning_log_app/new_topic.html', context)