[PYTHON] Create a Todo app with Django ④ Implement folder and task creation functions

Next, we will implement the folder and task creation functions.

List of articles

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

Implementation of folder creation function

URL settings

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')

Form creation

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")

Link to folder creation page

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">

template

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.

Verification

The folder creation function is now implemented! Try http: // localhost: 8000 / folders / create, and if it looks like the following, it's OK! フォルダー作成機能.png

Implementation of task creation function

URL settings

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')

Form creation

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.

Link to folder creation page

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">

template

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).

Template extension

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 %}

in conclusion

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!

List of articles

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

Recommended Posts

Create a Todo app with Django ④ Implement folder and task creation functions
Create a Todo app with Django ③ Create a task list page
Create a Todo app with Django ⑤ Create a task editing function
Create a Todo app with Django REST Framework + Angular
Create a Todo app with the Django REST framework
Create a Todo app with Django ① Build an environment with Docker
Web App Development Practice: Create a Shift Creation Page with Django! (Shift creation page)
Create a native GUI app with Py2app and Tkinter
Create a homepage with django
Web App Development Practice: Create a Shift Creation Page with Django! (Write a base template)
Web App Development Practice: Create a Shift Creation Page with Django! (Authentication system processing)
Web App Development Practice: Create a Shift Creation Page with Django! (Experiment on admin page)
Implement a Django app on Hy
Web App Development Practice: Create a Shift Creation Page with Django! (Design of database model)
Create a file uploader with Django
Create a temporary file with django as a zip file and return it
Create and deploy a Django (PTVS) app using Azure Table storage
Make a scraping app with Python + Django + AWS and change jobs
Create a GUI app with Python's Tkinter
Create a simple web app with flask
Create your first app with Django startproject
Implement a model with state and behavior
Ramen map creation with Scrapy and Django
Create a stack with a queue and a queue with a stack (from LetCode / Implement Stack using Queues, Implement Queue using Stacks)
How to develop a cart app with Django
Create a dashboard for Network devices with Django!
Let's make a nervous breakdown app with Vue.js and Django-Rest-Framework [Part 1] ~ Django setup ~
A simple to-do list created with Python + Django
Until you create a new app in Django
Try creating a web application with Vue.js and Django (Mac)-(1) Environment construction, application creation
[Go language] Create a TUI app with Elm Architecture Create a slightly rich ToDo app with bubble tea
I tried to create a table only with Django
What is a dog? Django App Creation Start Volume--startapp
Create a batch of images and inflate with ImageDataGenerator
What is a dog? Django App Creation Start Volume--startproject
Let's make a Mac app with Tkinter and py2app
Create a 3D model viewer with PyQt5 and PyQtGraph
Deploy a Django app made with PTVS on Azure
To myself as a Django beginner (4) --Create a memo app--
Create a django environment with docker-compose (MariaDB + Nginx + uWSGI)
[Linux] Create a self-signed certificate with Docker and apache
Create Django Todo list
When I deploy a Django app with Apache2 and it no longer reads static files
Steps to set up Pipenv, create a CRUD app with Flask, and containerize it with Docker
Create a shogi game record management app using Django 4 ~ Create View ~
[Python] Create a file & folder path specification screen with tkinter
Django Tutorial (Blog App Creation) ⑥ --Article Details / Editing / Deleting Functions
Create a web surveillance camera with Raspberry Pi and OpenCV
Create a machine learning app with ABEJA Platform + LINE Bot
Create applications, register data, and share with a single email
Let's create a PRML diagram with Python, Numpy and matplotlib.
Build a bulletin board app from scratch with Django. (Part 2)
Build a bulletin board app from scratch with Django. (Part 3)
Create an authentication feature with django-allauth and CustomUser in Django
Create a deploy script with fabric and cuisine and reuse it
Create a social integration API for smartphone apps with Django
[Python] Create a screen for HTTP status code 403/404/500 with Django
Todo app with django-bootstrap-modal-forms plugin
Create an API with Django
Create ToDo List [Python Django]
Web application creation with Django