Next, we will implement the folder and task creation functions.
Create a Todo app with Django ① Build an environment with Docker Create a Todo app with Django ② Create a folder list page Create a Todo app with Django ③ Create a task list page Create Todo app with Django ④ Implementation of folder and task creation function Create a Todo app with Django ⑤ Create a task editing function
First, set the URL based on the following definition.
URL | processing |
---|---|
/folders/create | Create a new folder |
To get this design, add the following sentence to todo / urls.py
.
todo/urls.py
path('create', views.create_folder, name='folders.create')
First, create a file called forms.py
under the todo
directory.
This file is the file you need to create the form.
Edit forms.py as follows.
forms.py
from django import forms
from .models import Folder
class FolderForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(FolderForm, self).__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs = {
'class': 'form-control'
}
class Meta:
model = Folder
fields = ('title',)
labels = {'title' : 'Folder name'}
The forms
and Folder
models needed to create a form are imported in lines 1 and 2.
In the \ _ \ _ init \ _ \ _ part, the class name of FolderForm is form-control. This is to apply bootstrap.
django has a class called django.forms.ModelForm that automatically creates a Field based on the Model class. It seems convenient to use the ModelForm class for registration and update processing.
The meanings of variables in the Meta class are as follows.
Variable name | meaning |
---|---|
model | Specify the Model class to be linked |
fields | Specify the target field to generate the input form from Model in tuple format |
labels | Change the display name of the input field. (For example, if not specified this time, the display name will be "title") |
Add the link as follows to the part of templates / index.html
where the folder is added
.
index.html
<a href="{% url 'folders.create' %}" class="btn btn-default btn-block">
Create create_folders.html
under the templates
directory.
Edit create_folders.html
as follows.
templates/create_folders.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Todo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootflat/2.0.4/css/bootflat.min.css">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<header>
<nav class="my-navbar">
<a class="my-navbar-brand" href="/">Todo</a>
</nav>
</header>
<main>
<div class="container">
<div class="row">
<div class="col col-md-offset-3 col-md-6">
<nav class="panel panel-default">
<div class="panel-heading">Add a folder</div>
<div class="panel-body">
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div class="text-right">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</form>
</div>
</nav>
</div>
</div>
</div>
</main>
</body>
</html>
CSRF measures are taken in the following parts.
templates/create_folders.html
{% csrf_token %}
In addition, the form for creating a folder is expanded in the following part.
create_folders.html
{{ form.as_p }}
What is ʻas_p`?
<p>
contents of form
</p>
It means that it will be developed in the form of.
Next, I will write a view.
View
Add the following create_folder
method to the view.
views.py
from django.shortcuts import render, get_object_or_404, redirect#Added redirect function
from .forms import FolderForm
def create_folder(request):
if request.method == "POST":
form = FolderForm(request.POST)
if form.is_valid():
folder = form.save(commit=False)
folder.created_at = timezone.now()
folder.save()
return redirect('tasks.index', id=folder.id)
else:
form = FolderForm()
return render(request, 'create_folders.html', {'form': form})
First of all, we are importing the FolderForm and redirect functions we created.
After that, we define the create_folder
function.
When data is added to request.POST, the processing of the if statement is written so that the contents entered in the form are saved in the database.
The folder creation function is now implemented! Try http: // localhost: 8000 / folders / create, and if it looks like the following, it's OK!
First, set the URL based on the following definition.
URL | processing |
---|---|
<int:id>/tasks/create | Create a new task |
To get this design, add the following sentence to todo / urls.py
.
todo/urls.py
path('<int:id>/tasks/create', views.create_task, name='tasks.create')
Create a form for task creation in forms.py. Add the following TaskForm class
todo/forms.py
from .models import Folder, Task#Import Task model
class TaskForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TaskForm, self).__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs = {
'class': 'form-control'
}
class Meta:
STATUS_CHOICES = [(1, 'Incomplete'),(2, 'Working'),(3, 'Done')]
model = Task
fields = ('title', 'status','due_date')
labels = {
'title': 'Task name',
'status': 'Status',
'due_date': 'Deadline',
}
First of all, we are importing the Task model.
And we are adding the TaskForm
class.
Add the link as follows to the Add task
part of templates / index.html
.
index.html
<a href="{% url 'tasks.create' id=current_folder
_id %}" class="btn btn-default btn-block">
Create create_tasks.html
under the templates
directory.
Edit create_tasks.html
as follows.
templates/create_tasks.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Todo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<link rel="stylesheet" href="https://npmcdn.com/flatpickr/dist/themes/material_blue.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootflat/2.0.4/css/bootflat.min.css">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<header>
<nav class="my-navbar">
<a class="my-navbar-brand" href="/">Todo</a>
</nav>
</header>
<main>
<div class="container">
<div class="row">
<div class="col col-md-offset-3 col-md-6">
<nav class="panel panel-default">
<div class="panel-heading">Add a task</div>
<div class="panel-body">
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div class="text-right">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</form>
</div>
</nav>
</div>
</div>
</div>
</main>
<script src="https://npmcdn.com/flatpickr/dist/flatpickr.min.js"></script>
<script src="https://npmcdn.com/flatpickr/dist/l10n/ja.js"></script>
<script>
flatpickr(document.getElementsByName('due_date'), {
locale: 'ja',
minDate: new Date()
});
</script>
</body>
</html>
Next, I will write a view.
View
Add the following create_task
method to the view.
views.py
from .forms import FolderForm, TaskForm#Import TaskForm
def create_task(request, id):
#Get the selected folder
current_folder = get_object_or_404(Folder, id=id)
if request.method == "POST":
form = TaskForm(request.POST)
if form.is_valid():
task = form.save(commit=False)
task.created_at = timezone.now()
task.folder_id = current_folder
task.save()
return redirect('tasks.index', id=current_folder.id)
else:
form = TaskForm()
return render(request, 'create_tasks.html', {'form': form}, {'id':current_folder.id})
The following parts should be noted.
task.folder_id = current_folder
folder_id
is a foreign key, but you need to pass an object when setting the foreign key (in this case the Folder object).
Templates are useful when you want to use the same information and layout in multiple places. You don't have to repeat it in each file.
To create the original template, create a base.html
file under the todo / templates
directory.
templates
├── base.html
├── create_folders.html
├── create_tasks.html
└── index.html
Edit base.html
as follows.
base.html
{% load static %}
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Todo</title>
{% block styles %}
{% endblock %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootflat/2.0.4/css/bootflat.min.css">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<header>
<nav class="my-navbar">
<a class="my-navbar-brand" href="{% url 'tasks.index' id=1 %}">Todo</a>
</nav>
</header>
<main>
{% block content %}
{% endblock %}
</main>
{% block scripts %}
{% endblock %}
</body>
</html>
The following part, HTML will be inserted.
{% block styles %}
{% endblock %}
You can extend base.html by writing the following at the beginning of the file.
{% extends 'base.html' %}
Based on this, edit create_folders.html
, create_tasks
, and ʻindex.html` as follows.
create_folders.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col col-md-offset-3 col-md-6">
<nav class="panel panel-default">
<div class="panel-heading">Add a folder</div>
<div class="panel-body">
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div class="text-right">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</form>
</div>
</nav>
</div>
</div>
</div>
{% endblock %}
create_tasks.html
{% extends 'base.html' %}
{% block styles %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<link rel="stylesheet" href="https://npmcdn.com/flatpickr/dist/themes/material_blue.css">
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col col-md-offset-3 col-md-6">
<nav class="panel panel-default">
<div class="panel-heading">Add a task</div>
<div class="panel-body">
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div class="text-right">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</form>
</div>
</nav>
</div>
</div>
<div>
{% endblock %}
{% block scripts %}
<script src="https://npmcdn.com/flatpickr/dist/flatpickr.min.js"></script>
<script src="https://npmcdn.com/flatpickr/dist/l10n/ja.js"></script>
<script>
flatpickr(document.getElementsByName('due_date'), {
locale: 'ja',
minDate: new Date()
});
</script>
{% endblock %}
index.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col col-md-4">
<nav class="panel panel-default">
<div class="panel-heading">folder</div>
<div class="list-group">
{% for folder in folders %}
<a
href="{% url 'tasks.index' id=folder.id %}",
class="list-group-item {% if current_folder_id == folder.id %}active{% endif %}"
>
{{ folder.title }}
</a>
{% endfor %}
</div>
<div class="panel-body">
<a href="{% url 'folders.create' %}" class="btn btn-default btn-block">
Add a folder
</a>
</div>
</nav>
</div>
<div class="column col-md-8">
<div class="panel panel-default">
<div class="panel-heading">task</div>
<table class="table">
<thead>
<tr>
<th>title</th>
<th>Status</th>
<th>Deadline</th>
<th></th>
</tr>
</thead>
<tbody>
{% for task in tasks %}
<tr>
<td>{{ task.title }}</td>
<td>
<span
class="label {% if task.status == 1 %}label-danger{% endif %}{% if task.status == 2 %}label-info{% endif %}"
>
{{ task.get_status_display }}
</span>
</td>
<td>{{ task.due_date }}</td>
<td><a href="{% url 'tasks.edit' id=current_folder_id task_id=task.id %}">Edit</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="panel-body">
<div class="text-right">
<a href="{% url 'tasks.create' id=current_folder_id %}" class="btn btn-default btn-block">
Add a task
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
This is the end of this chapter! The code so far can be found in the repository's chapter4 branch. In the next chapter, we will implement the task editing function!
Create a Todo app with Django ① Build an environment with Docker Create a Todo app with Django ② Create a folder list page Create a Todo app with Django ③ Create a task list page Create Todo app with Django ④ Implementation of folder and task creation function Create a Todo app with Django ⑤ Create a task editing function