Djangoで、自作ページのインラインフォームに追加ボタン

Python - Django
2018年10月18日11:45に更新(約27日前)
2018年10月18日11:34に作成(約27日前)

旧ブログ移行記事です。

概要

Djangoの管理画面でインラインフォームを使うと、インラインで表示させているデータを自由に追加できます。 どういうことかといいますと....

管理画面でインラインフォームを利用しています。下側に「Fileの追加」とありますね。

これを押すと、1行追加されます。

この機能を、自作のテンプレートでもつけ加えます。 インラインフォームを自作のテンプレートで使うには、こちらで解説しています。こちらのモデルやフォーム等を元に説明していきます。

forms.py

わかりやすいように、extra=1として、最初は1件しか表示されないようにしておきます。

FileFormset = forms.inlineformset_factory(
    Post, File, fields='__all__',
    extra=1, can_delete=False
)

models.pyやviews.pyは、インラインフォームセットの基本と同じ内容です。

base.html

Bootstrap4のスターターテンプレートそのままですが、後で追加のJavaScriptを書くため、下側で{% block extrajs %}と定義しておきます。

<!doctype html>
<html lang="ja">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

    <title>フォームセット</title>
  </head>
  <body>
    <div class="container mt-3">
        {% block content %}{% endblock %}
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
    {% block extrajs %}{% endblock %}
  </body>
</html>

post_form.html

{% extends 'app/base.html' %}

{% block content %}
<form action="" method="post" enctype="multipart/form-data">
    <h2>記事</h2>
    {{ form.as_p }}

    <h2>添付ファイル</h2>
    {{ formset.management_form }}
    <div id="file-area">
        {% for file_form in formset %}
            {{ file_form.as_p }}
            <hr>
        {% endfor %}
    </div>

    {% csrf_token %}
    <button type="submit" class="btn btn-primary">送信</button>
    <button id="add" type="button" class="btn btn-primary">ファイルの追加</button>
</form>

{% endblock %}

{% block extrajs %}
<script>
$(function(){
    var totalManageElement = $('input#id_file_set-TOTAL_FORMS');
    var currentFileCount = parseInt(totalManageElement.val());
    $('button#add').on('click', function(){
        var nameElement = $('<input>', {
            type: 'name',
            name: 'file_set-' + currentFileCount + '-name',
            id: 'id_file_set-' + currentFileCount + '-name',
        });
        var fileElement = $('<input>', {
            type: 'file',
            name: 'file_set-' + currentFileCount + '-src',
            id: 'id_file_set-' + currentFileCount + '-src',
        });
        $('div#file-area').append(nameElement);
        $('div#file-area').append(fileElement);
        currentFileCount += 1;
        totalManageElement.attr('value', currentFileCount);
    });
});
</script>
{% endblock %}

{% block content %}内はインラインフォームセットのときと同様ですが、要素を追加しやすくするため、<div id="file-area">という要素で囲んでいます。 {% block extrajs %}内で、ファイルを追加しています。

見た目

追加するボタンを押してみると...

見た目がちょっと雑ですが、入力欄が追加されました。送信しても、きちんと動きます。

記事にコメントする