1
0

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 5 years have passed since last update.

お店を自由に追加してみよう!CreateView編

Last updated at Posted at 2019-12-11

今回はCreateView編です。

今までTemplateViewを用いてListView、DetailViewを作成してまいりました。
その1-TemplateViewを使ってみよう!IndexView編
その2-TemplateViewをつかってみよう!Detailview編
お店の一覧、お店の詳細ページを表示ができるようになっている状態の続きと致します。

自分で好きなデータを追加できるって掲示板みたいで楽しいですよね!!

(見慣れない技術の解説)forms.pyでフォームの定義をおこなう

ここであらたなフォームという技術が現れました。
このforms機能はお仕事ではかなり使われることが多いので、慣れておくことを絶対にお勧めしています。
これは何なのかというと、pythonでこのform部分を作ってしまい、モデルと連動してhtmlの<form></form>を作成することになります。
最終的にwebサイトのフォーム部分を表示させることが目的となっていますので、怖がらずで大丈夫ですよ!

編集するファイルはこちら

mysite
│  db.sqlite3
│  manage.py
├─mysite
│  │  settings.py
│  │  urls.py
└─test_app
    │  admin.py
    │  apps.py
    │  models.py
    │  tests.py
    │  urls.py(ここをルーティング設定のために編集)
    │  views.py(ここをCreateView設定のために編集)
    │  forms.py(ここにお店追加の投稿フォームclassを作成)
    ├─migrations
    └─templates
       └─test_app
            └─list.html(ここにお店追加のリンクを表示)
               detail.html
               form.html(お店追加の投稿フォームを表示)

ルーティング設定

このURLでお店の作成ページにリンクできるように設定します。

http://localhost:8000/create

test_appのurls.pyにルーティングを設定します。

urls.py
from django.urls import path
from . import views

app_name = 'test_app'
urlpatterns = [
    path('index/',views.IndexView.as_view(),name='index'),
    path('<int:pk>/',views.DetailView.as_view(),name='detail'),
    path('create/',views.CreateView.as_view(),name='create'),#(ここを追加)
]

解説:app_nameとは、どのアプリ名に対してのルーティングファイルであるか指定する必要があります。ページ上のリンク(htmlで書かれたページのaタグで書かれたリンク)で<a href="{% url 'test_app:create' %}">と記述するため、test_appとアプリ名を設定する必要があります。
また、path('create/',views.CreateView.as_view(),name='create')ではcreate/のURLでviews.pyのCreateViewを呼び出しています。as_view()はテンプレートビューをビューとして扱うため使用されています。このas_view()を付けることによりビュー定義の記述がぐっと楽になります。テンプレートビュー限定のメリットですね。

CreateViewをviews.pyに設定

views.py
from django.views import generic
from .models import Shop
from .forms import ShopCreateForm #ここを追加

# Create your views here.
class IndexView(generic.ListView):
    model = Shop
    template_name = 'test_app/list.html'
class DetailView(generic.DetailView):
    model=Shop
    template_name = 'test_app/detail.html'

class CreateView(generic.CreateView):#ここ以降を追加
    model = Shop
    form_class = ShopCreateForm
    template_name = "test_app/form.html"
    success_url = "/index"

解説:form_classにforms.pyで投稿フォーム用に今回作成するフォームクラスであるShopCreateFormを指定しています。
ちゃんとimport ShopCreateFormを忘れずにお願いします。

views.pyとforms.pyを作成し、行ったり来たりするため、慣れるまで時間がかかりますが頑張りましょう!焦らず無理せず。
きっと慣れてさらに先に進めます!

お店投稿フォームをforms.pyに作成

forms.pyが作成されていない場合、新たに作成する場合があります。作成する場所はtest_appの直下です。views.pyやmodels.pyと同じレベルに作成します。
forms.pyはこのようになります。

forms.py
from django import forms
from .models import Shop

class ShopCreateForm(forms.ModelForm):
    class Meta:
        model = Shop
        fields = ("name","tell_num","address")

解説:forms.ModelFormとは、フォームを作成するためのdjangoの機能となっています。
モデルで定義されているフィールドをそのまま使います。
そのなかで、fieldsにてフォームで表示させるフィールドを選び、絞ることができます。

お店のデータを投稿したい場合、すでにShopのフィールドは作成されています。実際にmodels.pyの内容はこちらで、nametell_numaddresscreated_atなどフィールドが作成されています。

models.py
from django.db import models

# Create your models here.
class Shop(models.Model):
    #各フィールドの定義
    name = models.CharField('shopname',max_length=30)
    tell_num = models.CharField('tell_number',max_length=13)
    address = models.CharField('address',max_length=30)
    created_at = models.DateTimeField(auto_now_add=True)

    #admin画面の表示内容
    def __str__(self):
        return self.name

このShopクラスのフィールドをそのままforms.pyで使うことを意味しているのです。
ModelFormを用いると大変楽にフォームページを作成できるのです!

投稿ページのform.htmlを作成

mysite/test_app/templates/test_app/form.html
<!DOCTYPE>
<html>
    <head>
    </head>
    <body>
    <p>お店の作成</p>
        <form method="post">
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">save</button>
        </form>
    </body>
</html>

解説:<form method="post">でフォームタグを作成しています。
{% csrf_token %}はフォームデータに改ざん防止の特殊な何かのデータを添えて送信するもので、必須です。
これを入れないと、djangoがエラーとなるため、必ず入れましょう。
{{ form.as_p }}はforms.pyで作成したShopCreateFormをviews.pyのform_classで指定していたため、html側ではformと記述するだけでフォームが呼び出せます。formと書く、と刷り込ませて良いです!
<button type="submit">save</button>ではデータ送信ボタンを作成しています。」

「お店の投稿」リンクを一覧ページに作成

test_app/templates/test_app/list.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
  <p>一覧の表示</p>
  <p><a href="{% url 'test_app:create' %}">お店の追加</a></p><!-- この行を追加 -->
  <table>
    <tr>
    </tr>
    {% for shop in shop_list %}
    <tr>
      <td>{{ shop.name }}</td>
      <td><a href="{% url 'test_app:detail' shop.pk %}">詳細</a></td>
    </tr>
    {% endfor %}
  </table>
  </body>
</html>

解説:お店の追加ページへリンクするためにリンクを書いています。パスはtest_appというアプリ名のcreateを指定しています。

formの表示の確認を行う

「お店の追加フォーム画面」で団子屋という名前のお店を追加してみます。
create画面.png

「リスト画面」で追加されたデータを確認してみましょう。
クリエイト後トップ画面.png

「団子屋詳細画面」で団子屋の詳細を確認してみましょう。
団子屋詳細ページ.png

お疲れさまでした✨

最後に

データ追加のための設定は必ずと言っていいほど重要なdjangoスキルとなるでしょう。CreateViewを用いてスピーディに作成ができることでかなりDjangoに慣れているといえると思います。
3つくらい自分でアプリを作成してみれば、データの追加、詳細、一覧が含まれるような、お店掲示板、日記などのアプリケーションが作成できるようになっていると思います。

わからないところや質問など受け付けておりますので、一緒に頑張ってゆきましょう!

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?