11
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

django-bootstrap-modal-formsプラグインを使ったTodoアプリ

Last updated at Posted at 2020-03-22

概要

DjangoのCreateView、UpdateViewでBootstrapのModalフォームを使ったサンプルアプリを作りました。
”django-bootstrap-modal-forms”というプラグインの”BSModalCreateView”、”BSModalUpdateView”を使っています。
日本語のリファレンスや、小さい規模のサンプルアプリが見つからなかったので、まとめておきました。

環境

Python 3.8.0
Django 3.0.4
Bootstrap 4.1.3
プラグイン:django-bootstrap-modal-forms

インストール

  1. django-bootstrap-modal-formsプラグインのインストール
pip install django-bootstrap-modal-forms==1.5.0
  1. django-widget-tweaksのインストール
pip install django-widget-tweaks==1.4.5

やり方

settings.pyの編集

# myproject/myproject/settings.py  
INSTALLED_APPS = [
    ~
    'bootstrap_modal_forms',
    'widget_tweaks'
]

使用するModel

# mypeoject/myapp/models.py
import datetime
from django.db import models


class TodoItem(models.Model):
    item = models.CharField(max_length=50)
    item_date = models.DateField(default=datetime.date.today)
    user = models.ForeignKey(
        'auth.User',
        on_delete=models.CASCADE
    )

    def __str__(self):
        return self.item

forms.pyの編集

# mypeoject/myapp/forms.py
from bootstrap_modal_forms.forms import BSModalForm
from modalform.models import TodoItem


class CreateUpdateTodoItemForm(BSModalForm):
    class Meta:
        model = TodoItem
        fields = ['item', 'item_date']

views.pyの編集

# mypeoject/myapp/views.py
from bootstrap_modal_forms.generic import BSModalCreateView, BSModalUpdateView
from modalform.forms import CreateUpdateTodoItemForm
from modalform.models import TodoItem


def show_todo_items(request):
    all_items = TodoItem.objects.filter(user=request.user)
    return render(request, 'show_todo_items.html', {'all_items': all_items})


class CreateTodoItemFormView(BSModalCreateView):
    template_name = 'create_modal_form.html'
    form_class = CreateUpdateTodoItemForm
    success_message = 'Success: Item was created.'
    success_url = reverse_lazy('show_todo_items')

    def form_valid(self, form):
        form.instance.user_id = self.request.user.id
        return super(CreateTodoItemFormView, self).form_valid(form)


class UpdateTodoItemFormView(BSModalUpdateView):
    model = TodoItem
    template_name = 'update_modal_form.html'
    form_class = CreateUpdateTodoItemForm
    success_message = 'Success: Item was updated.'
    success_url = reverse_lazy('show_todo_items')


def delete_todo_item(request, todo_id):
    item = TodoItem.objects.get(pk=todo_id)
    item.delete()
    messages.success(request, ('Deleted successfully!'))
    return redirect('show_todo_items')

urls.pyの編集

from django.urls import path
from modalform import views

urlpatterns = [
    path('', views.show_todo_items, name='show_todo_items'),
    path('create_todo_item/', views.CreateTodoItemFormView.as_view(), name='create_todo_item'),
    path('update_todo_item/<int:pk>', views.UpdateTodoItemFormView.as_view(), name='update_todo_item'),
    path('delete_todo_item/<todo_id>', views.delete_todo_item, name='delete_todo_item'),
]

template(html)の作成

show_todo_items.htmlの作成

{% extends 'base.html' %}
{% load static %}
~
{% block content %}
    <!-- Todo追加フォーム -->
    <form class="form-inline my-2 my-lg-0" method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <button type="button" class="create_item bg-light rounded" data-id="{% url 'create_todo_item' %}"><span class="fa fa-pencil">Itemの登録</span></button>
    </form><br>

    <!-- modal  -->
    <div class="modal fade" tabindex="-1" role="dialog" id="modal">
        <div class="modal-dialog" role="document">
            <div class="modal-content"></div>
        </div>
    </div>

    <!-- TodoListテーブルの表示 -->
    {% if all_items %}
        <table class="table table-bordered tablesorter-bootstrap" id="recipe-table">
        <thead>
            <tr class="table-primary">
                <th style="text-align: center;">Item</th>
                <th style="text-align: center;">Date</th>
                <th style="text-align: center;">Edit</th>
                <th style="text-align: center;">Delete</th>
            </tr>
        </thead>
            <tbody>
            {% for i in all_items %}
                    <tr class="table-info">
                        <td style="text-align: center;">{{ i.item }}</td>
                        <td style="text-align: center;">{{ i.item_date|date:"n/j D" }}</td>
                        <td style="text-align: center;">
                            <button type="button" class="update_item bg-light rounded" data-id="{% url 'update_todo_item' i.pk %}"><span class="fa fa-pencil">Edit</span></button>
                        </td>
                        <td style="text-align: center;">
                            <button type="button" class="bg-light rounded"><a href="{% url 'delete_todo_item' i.id %}"><span class="fa fa-pencil">×</span></a></button>
                        </td>
                    </tr>
            {% endfor %}
            </tbody>
        </table>
    {% endif %}

<script type="text/javascript">

    {# Create Item Modal Form #}
    $(function () {
        $(".create_item").each(function () {
            $(this).modalForm({formURL: $(this).data('id')});
        });
    });
    {# Update Item Modal Form #}
    $(function () {
        $(".update_item").each(function () {
            $(this).modalForm({formURL: $(this).data('id')});
        });
    });
</script>
{% endblock content %}

create_modal_form.htmlの作成

{% load widget_tweaks %}

<form method="post" action="" autocomplete="off">
  {% csrf_token %}
  <div class="modal-header">
    <h3 class="modal-title">Create Item</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="button" class="btn btn-outline-secondary my-2 my-sm-0" data-dismiss="modal">Close</button>
    <button id="create" class="btn btn-outline-secondary my-2 my-sm-0" type="submit">Save</button>
  </div>

</form>

<script type="text/javascript">
    $('#id_item_date').datepicker({
        dateFormat: 'yy-mm-dd',
        autocomplete: "off"
    })
</script>

※この例では、日付の表示にdatepickerを使っています。
 フォームのidは"id_field名"で自動的に割り当てられます

update_modal_form.htmlの作成

{% load widget_tweaks %}

<form method="post" action="" autocomplete="off">
  {% csrf_token %}
  <div class="modal-header">
    <h3 class="modal-title">Update Item</h3>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>

  <div class="modal-body">
    <div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
      {% for error in form.non_field_errors %}
        {{ error }}
      {% endfor %}
    </div>

    {% for field in form %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {% render_field field class="form-control" placeholder=field.label %}
        <div class="{% if field.errors %} invalid{% endif %}">
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      </div>
    {% endfor %}
  </div>

  <div class="modal-footer">
    <button type="button" class="btn btn-outline-secondary my-2 my-sm-0" data-dismiss="modal">Close</button>
    <button id="update" class="btn btn-outline-secondary my-2 my-sm-0" type="submit">Update</button>
  </div>

</form>

<script type="text/javascript">
    $('#id_item_date').datepicker({
        dateFormat: 'yy-mm-dd',
        autocomplete: "off"
    })
</script>

※create_modal_form.htmlとほぼ同じです。
 モーダルタイトルをCreate Item→Update Item、ボタンをupdate→saveに修正しただけです。

Github

サンプルアプリのコードはGithubにアップしています。
Readmeにデモ動画も載せているので、以下のページを見てもらえると分かりやすいと思います。
Githubのページ

まとめ

プラグインdjango-bootstrap-modal-formsを使った、bootstrap4のmodalのCreateView、UpdateViewフォームの作り方を紹介しました。

Djangoでモーダルフォームを使ったサンプルが中々見つけられなかったので、参考にしていただければと思います。

11
14
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?