【 django 入門】 Django の class based view の使い方と カスタマイズ 方法

このドキュメントでは、Django の Class Based View について、 CRUD の実装方法について具体的に説明します。Djangoは、Webアプリケーションの開発に使用されるPythonのフレームワークの1つであり、Class Based Viewを使用することで、効率的にWebアプリケーションを開発することができます。

class based view での CRUD とは

CRUDとは、Create(作成)、Read(読み取り)、Update(更新)、Delete(削除)の頭文字を取ったもので、Webアプリケーションにおいて、データの作成、読み取り、更新、削除の機能を提供することを指します。

class based view で CRUDの実装方法

以下の手順に従って、CRUDを実装することができます。

  1. models.pyにモデルを定義する。
  2. forms.pyにフォームを定義する。
  3. views.pyにCreate View、Retrieve View、Update View、Delete Viewを定義する。
  4. urls.pyにURLを設定する。

1. models.pyにモデルを定義する

まずは、CRUDで使用するモデルを定義します。モデルは、データベースのテーブルに対応するPythonのクラスです。例えば、以下のようなmodels.pyファイルを作成します。

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    published_date = models.DateField()

この例では、Bookというモデルを定義しています。Bookモデルは、書籍のタイトル、著者、出版日を表す3つのフィールドを持っています。

2. forms.pyにフォームを定義する

次に、CRUDで使用するフォームを定義します。フォームは、WebページのHTMLフォームと対応するPythonのクラスであり、ユーザーが入力したデータを受け取り、バリデーションを行います。例えば、以下のようなforms.pyファイルを作成します。

from django import forms
from .models import Book

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['title', 'author', 'published_date']

この例では、BookFormというフォームを定義しています。BookFormは、Bookモデルと対応するフォームであり、titleauthorpublished_dateの3つのフィールドを持ちます。

3. views.pyにCreate View、Retrieve View、Update View、Delete Viewを定義する

次に、Create View、Retrieve View、Update View、Delete Viewを定義します。それぞれのViewには、CreateViewDetailViewUpdateViewDeleteViewというクラスを継承し、modelform_classsuccess_urlなどの属性を指定します。

Create View

Create Viewは、データの作成を行うためのViewです。例えば、以下のようなviews.pyファイルを作成します。

from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Book
from .forms import BookForm

class BookCreateView(CreateView):
    model = Book
    form_class = BookForm
    success_url = reverse_lazy('book_list')

この例では、BookCreateViewというCreate Viewを定義しています。BookCreateViewでは、BookモデルとBookFormフォームを使用し、データの保存が成功した場合にbook_listというURLに遷移します。

Retrieve View

Retrieve Viewは、データの読み取りを行うためのViewです。例えば、以下のようなviews.pyファイルを作成します。

from django.views.generic.detail import DetailView
from .models import Book

class BookDetailView(DetailView):
    model = Book

この例では、BookDetailViewというRetrieve Viewを定義しています。BookDetailViewでは、Bookモデルを使用し、book_detail.htmlというテンプレートを表示します。

Update View

Update Viewは、データの更新を行うためのViewです。例えば、以下のようなviews.pyファイルを作成します。

from django.views.generic.edit import UpdateView
from django.urls import reverse_lazy
from .models import Book
from .forms import BookForm

class BookUpdateView(UpdateView):
    model = Book
    form_class = BookForm
    success_url = reverse_lazy('book_list')

この例では、BookUpdateViewというUpdate Viewを定義しています。BookUpdateViewでは、BookモデルとBookFormフォームを使用し、データの保存が成功した場合にbook_listというURLに遷移します。

Delete View

Delete Viewは、データの削除を行うためのViewです。例えば、以下のようなviews.pyファイルを作成します。

from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
from .models import Book

class BookDeleteView(DeleteView):
    model = Book
    success_url = reverse_lazy('book_list')

この例では、BookDeleteViewというDelete Viewを定義しています。BookDeleteViewでは、Bookモデルを使用し、データの削除が成功した場合にbook_listというURLに遷移します。

4. urls.pyにURLを設定する

最後に、urls.pyで、各Viewに対応するURLを設定します。例えば、以下のようなurls.pyファイルを作成します。

from django.urls import path
from .views import BookListView, BookCreateView, BookDetailView, BookUpdateView, BookDeleteView

urlpatterns = [
    path('', BookListView.as_view(), name='book_list'),
    path('create/', BookCreateView.as_view(), name='book_create'),
    path('<int:pk>/', BookDetailView.as_view(), name='book_detail'),
    path('<int:pk>/update/', BookUpdateView.as_view(), name='book_update'),
    path('<int:pk>/delete/', BookDeleteView.as_view(), name='book_delete'),
]

この例では、urlpatternsに、BookListViewBookCreateViewBookDetailViewBookUpdateViewBookDeleteViewに対応するURLを設定しています。

これで、CRUDの実装が完了しました。

テンプレートの作成

テンプレートのディレクトリ階層については、Djangoの公式ドキュメントにおいても特に明確に定められていません。しかし、一般的には以下のようなディレクトリ階層を採用することが多いです。

myproject/
    myproject/
        settings.py
        urls.py
        ...
    myapp/
        templates/
            myapp/
                base.html
                book_list.html
                book_detail.html
                book_form.html
            ...
        views.py
        models.py
        ...
    ...

このように、アプリケーションごとにtemplatesディレクトリを作成し、その中にテンプレートを格納することが一般的です。さらに、templatesディレクトリ内に、各アプリケーションごとにサブディレクトリを作成し、その中にテンプレートを格納することが推奨されています。これにより、複数のアプリケーションを持つプロジェクトでも、テンプレートの管理が容易になります。

また、base.htmlなど、共通で使用するテンプレートは、アプリケーションごとに1つのファイルにまとめることが多いです。これにより、重複するコードを減らし、テンプレートの保守性を高めることができます。

テンプレートの継承

Djangoアプリケーションでは、各Viewで表示するHTMLのテンプレートを作成する必要があります。テンプレートは、Webページの構成要素を定義し、Viewが生成したデータを表示するためのものです。

Djangoにおけるテンプレートは、HTMLを拡張したものであり、テンプレートエンジンによって処理されます。テンプレートエンジンは、テンプレート内のタグや変数を解釈して、HTMLに変換します。Djangoには、デフォルトでdjango.template.backends.django.DjangoTemplatesというテンプレートエンジンが用意されており、柔軟なテンプレート処理を実現しています。

テンプレートを作成するには、まずテンプレートを継承するベーステンプレートを定義します。これにより、各Viewで表示するHTMLの共通部分をまとめることができます。例えば、以下のようなbase.htmlテンプレートを作成します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

テンプレートの定義

次に、各Viewで表示するHTMLのテンプレートを定義します。例えば、以下のようなbook_list.htmlテンプレートを作成します。

{% extends 'base.html' %}

{% block title %}書籍一覧{% endblock %}

{% block content %}
    <h1>書籍一覧</h1>
    <ul>
    {% for book in object_list %}
        <li><a href="{% url 'book_detail' book.pk %}">{{ book.title }}</a></li>
    {% empty %}
        <li>No books yet.</li>
    {% endfor %}
    </ul>
    <a href="{% url 'book_create' %}">新規作成</a>
{% endblock %}

この例では、{% extends 'base.html' %}によって、base.htmlを継承しています。{% block title %}{% endblock %}で囲まれた部分は、ページのタイトルを定義するための部分になります。{% block content %}{% endblock %}で囲まれた部分が、各Viewで表示するコンテンツになります。{% for %}{% endfor %}で囲まれた部分は、BookListViewで表示する書籍一覧の部分になります。{% empty %}は、書籍が存在しない場合に表示される文言です。{% url %}は、URLを動的に生成するためのテンプレートタグです。

BookDetailViewで表示するテンプレートも同様に定義します。例えば、以下のようなbook_detail.htmlテンプレートを作成します。

{% extends 'base.html' %}

{% block title %}{{ object.title }}{% endblock %}

{% block content %}
    <h1>{{ object.title }}</h1>
    <p><strong>著者:</strong> {{ object.author }}</p>
    <p><strong>出版日:</strong> {{ object.published_date }}</p>
    <a href="{% url 'book_update' object.pk %}">編集</a>
    <form action="{% url 'book_delete' object.pk %}" method="post">
        {% csrf_token %}
        <input type="submit" value="削除">
    </form>
{% endblock %}

この例では、{% extends 'base.html' %}によって、base.htmlを継承しています。{% block title %}{% endblock %}で囲まれた部分は、ページのタイトルを定義するための部分になります。{% block content %}{% endblock %}で囲まれた部分が、各Viewで表示するコンテンツになります。{{ object }}は、BookDetailViewで指定したmodelのインスタンスになります。{% url 'book_update' object.pk %}は、BookUpdateViewに対応するURLを動的に生成するためのテンプレートタグです。<form>タグは、書籍の削除を行うためのフォームです。{% csrf_token %}は、セキュリティ対策のために必要なテンプレートタグです。

BookCreateViewBookUpdateViewで表示するテンプレートも同様に定義します。例えば、以下のようなbook_form.htmlテンプレートを作成します。

{% extends 'base.html' %}

{% block title %}{{ form_title }}{% endblock %}

{% block content %}
    <h1>{{ form_title }}</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="保存">
    </form>
{% endblock %}

この例では、{% extends 'base.html' %}によって、base.htmlを継承しています。{% block title %}{% endblock %}で囲まれた部分は、ページのタイトルを定義するための部分になります。{% block content %}{% endblock %}で囲まれた部分が、各Viewで表示するコンテンツになります。{{ form_title }}は、フォームのタイトルを表します。{{ form.as_p }}は、フォームのフィールドを<p>タグで囲んで表示するためのテンプレートタグです。<form>タグは、フォームの送信を行うためのものです。

BookDeleteViewでは、テンプレートを定義する必要はありません。

フォームのバリデーション

Djangoのフォームは、クライアントサイドとサーバーサイドの両方でバリデーションを行うことができます。クライアントサイドのバリデーションは、JavaScriptを用いてブラウザ上で行われます。一方、サーバーサイドのバリデーションは、View内で行われます。

フォームのバリデーションは、forms.py内で行います。例えば、以下のようなBookFormを定義します。

from django import forms
from .models import Book

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ('title', 'author', 'published_date')

    def clean_title(self):
        title = self.cleaned_data['title']
        if len(title) < 3:
            raise forms.ValidationError('タイトルは3文字以上で入力してください。')
        return title

この例では、BookFormというフォームを定義しています。Metaクラスには、フォームで使用するモデルとフィールドを指定します。clean_titleメソッドは、titleフィールドのバリデーションを行うためのメソッドです。self.cleaned_dataには、フォームから送信されたデータが含まれています。len(title)でタイトルの文字数を取得し、3文字未満の場合は、forms.ValidationErrorでエラーを発生させます。

Viewでは、以下のようにバリデーションを行います。

from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Book
from .forms import BookForm

class BookCreateView(CreateView):
    model = Book
    form_class = BookForm
    template_name = 'book_form.html'
    success_url = reverse_lazy('book_list')

class BookUpdateView(UpdateView):
    model = Book
    form_class = BookForm
    template_name = 'book_form.html'
    success_url = reverse_lazy('book_list')

class BookDeleteView(DeleteView):
    model = Book
    success_url = reverse_lazy('book_list')

この例では、BookCreateViewBookUpdateViewで使用するフォームとして、BookFormを指定しています。フォームのバリデーションは、BookFormclean_titleメソッドで実行されます。バリデーションに失敗した場合は、エラーメッセージが表示されます。

フォームのバリデーションは、データの正当性を確認するために非常に重要な処理です。クライアントサイドのバリデーションだけでなく、サーバーサイドのバリデーションも行うことで、より信頼性の高いWebアプリケーションを開発することができます。

class based view のクラスのカスタマイズ

DjangoのClass-Based View(以下、CBV)の中でも、よく使われるビューには以下の4つがあります。

  1. CreateView
  2. UpdateView
  3. DeleteView
  4. DetailView

それぞれのビューについて、カスタマイズ方法を説明します。

CreateViewのカスタマイズ

CreateViewは、モデルに新しいレコードを追加するためのビューです。フォームを提供し、フォームの入力値をモデルの新しいレコードとして保存します。

CreateViewをカスタマイズするには、以下の手順を踏みます。

  1. CreateViewを継承する
  2. ビューで利用するフォームクラスを指定する
  3. フォームの入力値を保存するためのメソッドをオーバーライドする

例えば、以下のようにします。

from django.views.generic.edit import CreateView
from .models import Book
from .forms import BookForm

class BookCreateView(CreateView):
    model = Book
    form_class = BookForm
    template_name = 'book_create.html'

    def form_valid(self, form):
        # フォームの入力値を保存する処理を実装する
        return super().form_valid(form)

この例では、BookCreateViewというクラスを定義しています。CreateViewを継承しているため、model属性にBookモデルを、form_class属性にはフォームクラスを指定することで、フォームを提供し、フォームの入力値をBookモデルの新しいレコードとして保存するViewとして利用することができます。template_name属性には、テンプレートファイルのパスを指定します。

form_validメソッドをオーバーライドすることで、フォームの入力値を保存するための処理をカスタマイズすることができます。例えば、以下のように書くことで、フォームの入力値を保存する前に、ユーザー名をログに出力することができます。

def form_valid(self, form):
    logger.info('User {} created a new book'.format(self.request.user.username))
    return super().form_valid(form)

UpdateViewのカスタマイズ

UpdateViewは、モデルの既存のレコードを更新するためのビューです。フォームを提供し、フォームの入力値をモデルの既存のレコードとして保存します。

UpdateViewをカスタマイズするには、以下の手順を踏みます。

  1. UpdateViewを継承する
  2. ビューで利用するフォームクラスを指定する
  3. フォームの入力値を保存するためのメソッドをオーバーライドする

例えば、以下のようにします。

from django.views.generic.edit import UpdateView
from .models import Book
from .forms import BookForm

class BookUpdateView(UpdateView):
    model = Book
    form_class = BookForm
    template_name = 'book_update.html'

    def form_valid(self, form):
        # フォームの入力値を保存する処理を実装する
        return super().form_valid(form)

この例では、BookUpdateViewというクラスを定義しています。UpdateViewを継承しているため、model属性にBookモデルを、form_class属性にはフォームクラスを指定することで、フォームを提供し、フォームの入力値をBookモデルの既存のレコードとして保存するViewとして利用することができます。template_name属性には、テンプレートファイルのパスを指定します。

form_validメソッドをオーバーライドすることで、フォームの入力値を保存するための処理をカスタマイズすることができます。

DeleteViewのカスタマイズ

DeleteViewは、モデルの既存のレコードを削除するためのビューです。確認画面を提供し、モデルの既存のレコードを削除します。

DeleteViewをカスタマイズするには、以下の手順を踏みます。

  1. DeleteViewを継承する
  2. ビューで利用するモデルを指定する
  3. モデルの既存のレコードを削除するためのメソッドをオーバーライドする

例えば、以下のようにします。

from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
from .models import Book

class BookDeleteView(DeleteView):
    model = Book
    template_name = 'book_delete.html'
    success_url = reverse_lazy('book_list')

    def delete(self, request, *args, **kwargs):
        # モデルの既存のレコードを削除する処理を実装する
        return super().delete(request, *args, **kwargs)

この例では、BookDeleteViewというクラスを定義しています。DeleteViewを継承しているため、model属性にBookモデルを指定することで、モデルの既存のレコードを削除するViewとして利用することができます。template_name属性には、テンプレートファイルのパスを指定します。success_url属性には、レコードの削除に成功した場合に遷移するURLを指定します。

deleteメソッドをオーバーライドすることで、モデルの既存のレコードを削除するための処理をカスタマイズすることができます。

DetailViewのカスタマイズ

DetailViewは、モデルの既存のレコードの詳細を表示するためのビューです。

DetailViewをカスタマイズするには、以下の手順を踏みます。

  1. DetailViewを継承する
  2. ビューで利用するモデルを指定する
  3. テンプレートに渡すコンテキストデータをカスタマイズするためのメソッドをオーバーライドする

例えば、以下のようにします。

from django.views.generic import DetailView
from .models import Book

class BookDetailView(DetailView):
    model = Book
    template_name = 'book_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # テンプレートに渡す変数を追加する処理を実装する
        return context

この例では、BookDetailViewというクラスを定義しています。DetailViewを継承しているため、model属性にBookモデルを指定することで、モデルの既存のレコードの詳細を表示するViewとして利用することができます。template_name属性には、テンプレートファイルのパスを指定します。

get_context_dataメソッドをオーバーライドすることで、テンプレートに渡すコンテキストデータをカスタマイズすることができます。例えば、以下のように書くことで、BookDetailViewbookという変数を追加することができます。

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    book = Book.objects.get(pk=self.kwargs['pk'])
    context['book'] = book
    return context

Class based viewの利点と欠点まとめ

DjangoのClass-Based View(以下、CBV)は、Djangoアプリケーションの開発において、より抽象化された方法でViewを定義することができる機能です。CBVを使用すると、標準的なViewよりも多くの機能を提供することができます。

CBVの利点には、以下のようなものがあります。

  • コードの再利用性が高い
  • 共通のコードをまとめることができる
  • クラス継承を使用することで、複雑なViewを簡単に実装できる
  • 柔軟性が高い

一方、CBVの欠点としては、以下のようなものがあります。

  • Viewの機能が増えることで、初心者には理解しにくくなる
  • Viewの動作がオーバーライドされることがあるため、デバッグが難しくなることがある
  • テンプレートの変数の渡し方が複雑になることがある

CBVは、Django開発の効率化に大きく貢献している機能の一つです。CBVを使用することで、より簡潔で柔軟性の高いアプリケーションを開発することができます。

Udemy 独学でのアプリ開発に限界を感じたら

プログラミング初学者の皆さんに、 Udemy を強くお勧めしたいと思います。 Udemy は世界中のトップレベルのプログラミング講師が提供するオンライン講座を取り揃えています。以下は、 Udemy で学ぶことのメリットについての詳細です。

1. Udemy の豊富なコースの選択肢

Udemyには、数千ものコースがあります。初心者から上級者まで、プログラミングのあらゆるレベルを網羅しています。また、様々なプログラミング言語やツールに関するコースも多数あり、希望に合わせたコースを選ぶことができます。

2. 実践的な学習方法

Udemyのコースは、理論だけでなく実践的な学習も行えます。多くのコースには、プログラムの作成や実際のプロジェクトに取り組む演習が含まれています。これにより、理論だけでなく実践的なスキルも身につけることができます。

3. Udemy には質の高い講師陣

Udemyの講師陣には、世界中のトップレベルのプログラマーが多数在籍しています。彼らは、実務での経験を活かして、分かりやすい講義を行っています。

4. 初学者が始めるのにとても手頃な価格

Udemyのコースは、他のオンライン講座と比べて手頃な価格で提供されています。また、一度購入すると、終身アクセスが得られるので、自分のペースで学習することができます。

以上の理由から、プログラミング初学者の方には、Udemyが最適な学習プラットフォームであると考えられます。ぜひ一度、Udemyのコースを体験してみてください。


ウェブ開発の人気オンラインコース


ITとソフトウェアの人気オンラインコース


デザインの人気オンラインコース