見出し画像

DjangoとVue.jsでシンプルなTodoアプリを作る 05.DjangoだけでTodo一覧・作成機能を実装する

前回の記事では、Djangonの管理画面を使用して、データを登録できるようにしました。

今回の記事では、Vueを使用せず、Djangoのみで登録したデータを取得、作成できるようにしていきたいと思います。

まず、task/templates/task_list.html に、下記を追記してください。

task/templates/task_list.html

{% extends 'base.html' %}

{% block content %}
    {# 追記ここから #}
    <div class="mt-5">
        <div class="card mb-2">
            <div class="card-body">
                <div class="form-check">
                    <input class="form-check-input" type="checkbox">
                    <label class="form-check-label">
                        タスク
                    </label>
                    <button type="button" class="close float-right">
                        <span>&times;</span>
                    </button>
                </div>
            </div>
        </div>
    </div>
    {# 追記ここまで #}
{% endblock %}

追記すると、下記の写真のような感じになっていると思います。

チェックしたり、バツを押しても今は特に何もなりませんが、今後の完成イメージとして載せています。

いまは、「タスク」という文字が表示されていますが、これを先程 django の管理画面で作成した値に変えていこうと思います。

まず、task/views.py を開き、下記のようにコードを変更します。

from django.shortcuts import render
from django.views.generic import View

from .models import Task


class TaskView(View):
    def get(self, request):
        params = {}
        params['task'] = Task.objects.all()
        return render(request, "task_list.html", params)

そして、下記のように html を書き換えます。

{% extends 'base.html' %}
{% block content %}

<div class="mt-5">
  {# 追記 #}
  {% for t in task %}
  <div class="card mb-2">
    <div class="card-body">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" />
        <label class="form-check-label">
          {# 変更 #}
          {{ t.title }}
        </label>
        <button type="button" class="close float-right">
          <span>&times;</span>
        </button>
      </div>
    </div>
  </div>
    {# 追記 #}
  {% endfor %}
</div>

{% endblock %}


すると、写真のように、先程管理画面から登録した値に書き換わりました!


いきなり何をやったのかわからないと思うので、説明していきます。

TaskView の変更について

TaskView の get メソッドに、ざっくりやっていることを説明すると
params という辞書型の変数を定義し、params に task という key を定義し、value に Task モデルのデータを詰め込んで、task_list.html に渡して、ページ上でデータを表示できるようにしました。

実際に print(params)と views.py に記述すると、ターミナルで'task'という key に Task オブジェクトが value(値)として詰め込まれている事がわかります。

    def get(self, request):
        params = {}
        params["task"] = Task.objects.all()
        # 追記
        print(params)
{'task': <QuerySet [<Task: 卵を買う>, <Task: 新年の目標を立てる>]>}

辞書型のデータとは?

簡単に言うと、{}の中に、カンマで区切ってキーと対応する値の組み合わせを
{キー:値, キー:値....}というふうに保存できるデータのことです。
django では配列と同じくらい使うので、わからない方は調べたほうが良いと思います。
参考:https://www.javadrive.jp/python/dictionary/

django の Task オブジェクトの取得方法

views.py では、Task.objects.all()というふうにデータを持ってきました。
これは、django の Queryset クラスに基づいて作られたオブジェクト特有のデータの持ってくる方法です。
例えば、数字は、int 型、文字列は str 型というクラスがあります。
django のモデルも、Queryset 型というクラスがあり、特有のデータの処理の方法があるので、それを理解する必要があります。

詳しい内容は、公式ドキュメントを参照してほしいのですが、基本的に
(モデル名).objects.(命令)というふうにデータを取得します。

今回の場合、Task.objects.all()は
「Task のデータをすべて持ってくる」という内容です。

参考:https://codor.co.jp/django/about-queryset

HTML の変更について

HTML では、

{% for t in task %}
    {{ t.title }}
{% endfor %}

という記述の追加がありました。

{% %} {{ }}ですが、これは django 特有のテンプレートタグというものです。
参考: https://docs.djangoproject.com/ja/4.0/topics/templates/

{% %}は、HTML 内で、何かの動作を行うことを示しています。
具体的に今回の場合は、for で task オブジェクトのデータを
ループをするという動作をさせています。

{% for t in task %}
    {{ t.title }}
{% endfor %}

{{ t.title }}で、for でループさせた task オブジェクトを表示させています。
今回の場合は、task の title のデータを表示させています。

続いて、Task を投稿できるようにしたいと思います。
まず、html に、投稿できそうなフォームと、ボタンを用意します。

{% extends 'base.html' %}
{% block content %}

{# 追記ここから #}
<form>
  <div class="form-group row">
      <div class="col-9">
          <input type="text" class="form-control" placeholder="卵を買う">
      </div>
      <div class="col-3">
          <button type="submit" class="btn btn-primary mt-auto">タスクを追加</button>
      </div>
  </div>
</form>
{# 追記ここまで #}

<div class="mt-5">
  {% for t in task %}

実際には投稿できないので、注意してください。笑


続いて、forms.py というディレクトリを新しく作成し、Task 投稿フォームの裏側を作っていきます。
task/forms.py を作成してください。
作成したら、下記のように書いてください。

from django import forms

from .models import Task


class TaskForm(forms.ModelForm):
    class Meta:
        model = Task
        fields = ["title"]
        widgets = {
            "title": forms.TextInput(attrs={"class": "form-control", "placeholder": "卵を買う"}),
        }

django における forms.py とは

新しいデータを html から django に送るときに、html に直接 input タグを記述して、送る方法がありますが、コードが多くなったり、煩雑になります。
ですが、Django に備わっている親クラスのメソッドを継承し、forms.py を使用することで、簡単にデータを html から受け取り、保存することが可能です。

form の作成方法

TaskFormという、Task を作成するための form クラスを定義します。
forms.ModelForm という、Django の親クラスのメソッドを継承するクラスです。
これは、model に紐付いたデータを作れることができます。
class Meta以下にある、記述としては、TaskForm は、Task モデルの、title フィールドを受け取る form なことを示しています。
また、form は、class や placeholder を html 上から設定できないので、widgetsで、設定しています。これは設定しても、しなくてもダイジョブです。

続いて、views.py に、Task を form を通して投稿できるように メソッドを書いていきます。
html も、それに伴って変更していきます。

task/views.py

from django.shortcuts import redirect, render
from django.views.generic import View

from .forms import TaskForm
from .models import Task


class TaskView(View):
    def get(self, request):
        params = {}
        params["task"] = Task.objects.all()
        # 追記
        params["form"] = TaskForm()
        return render(request, "task_list.html", params)
    # 追記
    def post(self, request):
        form = TaskForm(request.POST)
        if form.is_valid():
            form.save()
        return redirect("task_list")

task/templates/task_list.html

{% extends 'base.html' %}
{% block content %}

{# 変更 #}
<form method="POST">
  {% csrf_token %}
  <div class="form-group row">
      <div class="col-9">
          {{ form.title }}
      </div>
{# 変更ここまで #}
      <div class="col-3">
          <button type="submit" class="btn btn-primary mt-auto">タスクを追加</button>
      </div>
  </div>
</form>

上記のようにコードを記述し、http://localhost:8000 で、文字を入力し、タスクを追加を押すと、一覧に入力した文字が追加されるようになると思います!

task/views.pyのpostメソッドについて

post メソッドは、TaskForm を通して、task を作成して django 内に保存するメソッドです。
一行ずつ説明すると、
form = TaskForm(request.POST)で、html から送信されたデータを、TaskForm に詰め込み、
そのデータが正しければ、form.is_valid()の条件分岐に入り、form.save()で、
Task のデータが保存されます。
return redirect("task_list")で、task_listのページにリダイレクトされます。
ここで、task_list とは、urls.py で定義した、name が task_list のページです。
path("", TaskView.as_view(), name="task_list"),
そのため、Task 一覧ページにリダイレクトされます。

get メソッドでも投稿フォームが見えて、投稿できるようにするために、
params["form"] = TaskForm()と定義する必要があります。

{% csrf_token %}とは

html では、form method="POST"と{% csrf_token %}を定義して、
form タグ から、データを投稿できるようにしました。
csrf_token とは、CSRF(クロスサイトリクエストフォージェリ)を検証する仕組みで、データを変更するときには、必ず記述する必要があります。
web サービスに CSRF の対策をしないと、悪意のあるユーザーに攻撃される可能性があります。そのため、Django では、基本的に{% csrf_token %}を定義していないと、データを変更できないようになっています。

今回の記事では、DjangoだけでTodo一覧・作成機能を実装しました。
次回の記事では、VueでTodoデータを取得できるようにしたいと思います!

次回も読みたい方は、スキを貰えると嬉しいです。

おまけ記事

⏩webサービスの作り方が気になったら


⏩Djanogを学ぶメリットについてはこちら



この記事が気に入ったらサポートをしてみませんか?