In this chapter, we will create a task list page.
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, create a task table. The definition of the task table is as follows.
Column logical name | Column physical name |
---|---|
ID | id |
folderID | folder_id |
title | title |
Status | status |
Created date | created_at |
Based on this, we will edit models.py
. Add the following Task model.
todo/models.py
class Task(models.Model):
STATUS_CHOICES = [(1, 'Incomplete'),(2, 'Working'),(3, 'Done')]
title = models.CharField(max_length=100)
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
due_date = models.DateField(default=timezone.now)
created_at = models.DateTimeField(default=timezone.now)
updated_at = models.DateTimeField(blank=True, null=True)
folder_id = models.ForeignKey(Folder, on_delete = models.CASCADE)
def publish(self):
self.update_at = timezone.now()
self.save()
def __str__(self):
return self.title
There are two points here.
The first is the status
part.
todo/models.py
STATUS_CHOICES = [(1, 'Incomplete'),(2, 'Working'),(3, 'Done')]
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
I set the status to IntergerField, but I set the default value to 1. The initial state when a task is created is always "incomplete", so if nothing is specified, "1" is entered. In addition, the choices option assigns incomplete, working, and completed to integers.
The second is the folder_id
part.
todo/models.py
folder_id = models.ForeignKey(Folder, on_delete = models.CASCADE)
ForeignKey links the Folder model and the Task model. In the on_delete = ... part, you can delete all the objects associated with the object to be deleted by setting CASCADE. This article is easy to understand with concrete examples. (By the way, "cascade" means "small waterfalls with many steps", and if you remember this, it is easy to understand that objects are deleted in a row)
At this point, create a migration file with make migraions
.
Execute the following command.
$ docker-compose run web python3 manage.py makemigrations
When executed, it will be as follows, and a new migration file will be created in the todo / migrations
directory.
$ docker-compose run web python3 manage.py makemigrations
Starting django_todo_db_1 ... done
Migrations for 'todo':
todo/migrations/0002_task.py
- Create model Task
Now that you have created the migration file, run the following command to migrate it.
$ docker-compose run web python3 manage.py migrate
When executed, it will be as follows.
docker-compose run web python3 manage.py migrate
Starting django_todo_db_1 ... done
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, todo
Running migrations:
Applying todo.0002_task... OK
After migrating, check the admin site (http: // localhost: 8000 / admin /). Then, although I should have migrated the Task model, the item related to Task does not appear.
To view the Task model, you need to import the Task model in admin.py. Add it to admin.py as follows.
todo/aadmin.py
from django.contrib import admin
from .models import Folder, Task#add to
admin.site.register(Folder)
admin.site.register(Task)#add to
If you visit the admin site again, you will see that the Tasks item has been added under Folders as shown in the image below.
Again, let's add some tasks on the admin site.
Edit views.py
as follows.
todo/views.py
from django.shortcuts import render, get_object_or_404#add to
from django.utils import timezone
from .models import Folder, Task#add to
def index(request, id):
#Get all folders
folders = Folder.objects.filter(created_at__lte=timezone.now()).order_by('created_at')
#Get the selected folder
current_folder = get_object_or_404(Folder, id=id)
#Get tasks for the selected folder
tasks = Task.objects.filter(folder_id = current_folder.id)
return render(request, 'index.html', {
'folders':folders,
'tasks':tasks,
'current_folder_id': current_folder.id,
})![Screenshot from 2020-04-17 11-03-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370196/2effc6d9-ccd6-3485-3eaa-4dceb2ae76da.png)
[Get_object_or_404 function] on the first line
Import (https://docs.djangoproject.com/ja/3.0/topics/http/shortcuts/#get-object-or-404).
The third line imports the Task model defined in models.py
.
In the get_object_or_404
function, if thepk (primary key)
in the Folder model, that is, the ʻid that matches the ʻid
is received, the object corresponding to the ʻid is assigned to the
current_folder. If you receive a ʻid
that does not exist in the Folder model's ʻid`, you will get a 404 error.
For example, if only 3 Folders are inserted, accessing http: // localhost: 8000 / folders / 5 / tasks will result in a 404 error as shown below.
Next, about this part.
tasks = Task.objects.filter(folder_id = current_folder.id)
Here, the filter
function is used to get all the tasks whose folder_id
of the task is equal to ʻid of the selected folder and assign it to
tasks`.
To see the list of tasks, insert the following code in templates / index.html
where the comment<!-Tasks are displayed here->
.
templates/index.html
<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="#">Edit</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="panel-body">
<div class="text-right">
<a href="#" class="btn btn-default btn-block">
Add a task
</a>
</div>
</div>
</div>
I think the following parts should be noted.
<span
class="label {% if task.status == 1 %}label-danger{% endif %}{% if task.status == 2 %}label-info{% endif %}"
>
{{ task.get_status_display }}
</span>
To get the "name" of the field whose value is limited by the choice attribute, you need to use the get_status_display method. (The get_status_display method is defined arbitrarily. For more information, see How to get the "name" of a field whose value is limited by the choice attribute in Django's model / 37bf4f5f6b60ccccebe2))
Also, using an if statement, when task.status is 1, that is, when it is incomplete, label-danger
is used, and when task.status is 2, that is, when it is working, label-info
is used. Allocation and css are applied for each task state.
When you get here, go to http: // localhost: 8000 / folders / 1 / tasks to check it out! It's OK if it looks like the following!
You have now listed the tasks! The code so far can be found in the repository chapter3 branch. Next, we will implement the folder creation 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