「views.py」の書き方には「関数ベース」と「クラスベース」がありますが、
今回はクラスベースでのビューの書き方をみていきます。
前提
・「my_app」というアプリを作成、「settings.py」に登録
・「manage.py」と同じ階層に「templates」「static」ディレクトリを作成し、読込先のディレクトリのパスをこちらに変更
.
.
.
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATE_DIR = os.path.join(BASE_DIR, 'templates')
STATIC_DIR = os.path.join(BASE_DIR, 'static').
.
.
.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR,],
.
.
.
STATIC_URL = '/static/'
STATICFILES_DIRS = (
STATIC_DIR,
)
・プロジェクトディレクトリの「urls.py」に以下のようにパスを登録
path('my_app/', include('my_app.urls')),
基本の利用法
get()メソッド
「views.py」の修正
from django.shortcuts import render
from django.views.generic.base import (
View,
)
# Create your views here.
class IndexView(View):
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
「urls.py」の作成
from django.urls import path
from .views import IndexView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
]
クラス.as_view() と指定することで、
クラスの get()メソッドを呼び出すことができます。
HTMLファイルの作成
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<div class="container py-4">
{% block content %}
{% endblock %}
</div>
</body>
</html>
{% extends 'base.html' %}
{% block content %}
<h1>Index</h1>
{% endblock %}
「/my_app/index」にアクセスしたときの表示↓

post()メソッド
モデルの作成
from django.db import models
# Create your models here.
class BaseModel(models.Model):
created_at = models.DateTimeField()
updated_at = models.DateTimeField()
class Meta:
abstract = True
class Book(BaseModel):
name = models.CharField(max_length=255)
description = models.CharField(max_length=1000)
price = models.IntegerField()
class Meta:
db_table = 'books'
マイグレーションの実行
python manage.py makemigrations my_app
python manage.py migrate
「forms.py」の作成
from django import forms
from .models import Book
from datetime import datetime
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['name', 'description', 'price']
def save(self, *args, **kwargs):
obj = super(BookForm, self).save(commit=False)
obj.created_at = datetime.now()
obj.updated_at = datetime.now()
obj.save()
return obj
「views.py」の修正
from django.shortcuts import render
from django.views.generic.base import (
View,
)
from . import forms
# Create your views here.
class IndexView(View):
def get(self, request, *args, **kwargs):
book_form = forms.BookForm()
return render(request, 'index.html', context={
'book_form': book_form,
})
def post(self, request, *args, **kwargs):
book_form = forms.BookForm(request.POST or None)
if book_form.is_valid():
book_form.save()
return render(request, 'index.html', context={
'book_form': book_form
})
「index.html」の修正
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ book_form.as_p }}
<input type="submit" value="送信">
</form>
{% endblock %}
「/my_app/index」にアクセスし、任意の値を入力して送信します。

すると、正常にデータベースに登録できているのが確認できます。

TemplateView
HTMLファイルの作成
{% extends 'base.html' %}
{% block content %}
<h1>Home</h1>
{% endblock %}
単純に特定のファイルを表示させたい場合
パスの追加
from django.views.generic.base import TemplateView
.
.
.
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home', TemplateView.as_view(template_name='home.html'), name='home'),
]
「/my_app/home」にアクセスすると「Home」と表示されます。
テンプレートにデータを渡したい場合
「home.html」の修正
{% extends 'base.html' %}
{% block content %}
<h1>Home</h1>
<p>現在時刻: {{ time }}</p>
{% endblock %}
「views.py」の修正
from django.shortcuts import render
from django.views.generic.base import (
View, TemplateView
)
from datetime import datetime
.
.
.
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['time'] = datetime.now()
return context
パスの追加
from django.urls import path
from .views import IndexView, HomeView
# from django.views.generic.base import TemplateView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
# path('home', TemplateView.as_view(template_name='home.html'), name='home'),
path('home', HomeView.as_view(), name='home'),
]
「/my_app/home」にアクセスすると、以下のように表示されます。

URLパラメータの利用
パスの修正
from django.urls import path
from .views import IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
]
「views.py」の修正
.
.
.
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['name'] = kwargs.get('name')
context['time'] = datetime.now()
return context
「home.html」の修正
{% extends 'base.html' %}
{% block content %}
<h1>Home</h1>
<p>こんにちは、{{ name }}さん</p>
<p>現在時刻: {{ time }}</p>
{% endblock %}
「/my_app/home/taro」にアクセスすると、URLパラメータを渡せていることが確認できます。

DetailView
「views.py」の修正
.
.
.
from .models import Book
from django.views.generic.detail import DetailView
.
.
.
class BookDetailView(DetailView):
model = Book
template_name = 'book.html'
パスの追加
from django.urls import path
from .views import BookDetailView, IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
path('detail_book/<int:pk>', BookDetailView.as_view(), name='detail_book'),
]
HTMLファイルの作成
{% extends 'base.html' %}
{% block content %}
<p>{{ object.name }}</p>
<p>{{ object.description }}</p>
<p>{{ object.price }}円</p>
{% endblock %}
「/my_app/detail_book/1」にアクセスしたときの表示

ListView
「views.py」の修正
.
.
.
from django.views.generic.list import ListView
.
.
.
class BookListView(ListView):
model = Book
template_name = 'book_list.html'
パスの追加
from django.urls import path
from .views import BookDetailView, BookListView, IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
path('detail_book/<int:pk>', BookDetailView.as_view(), name='detail_book'),
path('list_books', BookListView.as_view(), name='list_books'),
]
HTMLファイルの作成
{% extends 'base.html' %}
{% block content %}
<table class="table">
<tbody>
{% for object in object_list %}
<tr>
<td>名前: <a href="{% url 'my_app:detail_book' object.id %}">{{ object.name }}</a></td>
<td>金額: {{ object.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
「/my_app/list_books」にアクセスしたときの表示

並び替え
金額順で並び替え
.
.
.
class BookListView(ListView):
model = Book
template_name = 'book_list.html'
def get_queryset(self):
qs = super(BookListView, self).get_queryset()
qs = qs.order_by('price')
return qs

絞り込み
.
.
.
class BookListView(ListView):
model = Book
template_name = 'book_list.html'
def get_queryset(self):
qs = super(BookListView, self).get_queryset()
qs = qs.filter(name__startswith='ハリーポッター')
qs = qs.order_by('price')
return qs

CreateView
「views.py」の修正
.
.
.
from django.views.generic.edit import (
CreateView
)
.
.
.
class BookCreateView(CreateView):
model = Book
fields = ['name', 'description', 'price']
template_name = 'add_book.html'
def form_valid(self, form):
form.instance.created_at = datetime.now()
form.instance.updated_at = datetime.now()
return super(BookCreateView, self).form_valid(form)
パスの追加
from django.urls import path
from .views import BookCreateView, BookDetailView, BookListView, IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
path('detail_book/<int:pk>', BookDetailView.as_view(), name='detail_book'),
path('list_books', BookListView.as_view(), name='list_books'),
path('add_book', BookCreateView.as_view(), name='add_book'),
]
HTMLファイルの作成
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="保存">
</form>
{% endblock %}
遷移先ページの指定
データを保存後に遷移するページの指定方法は2通りあります。
「views.py」で指定
.
.
.
from django.urls import reverse_lazy
.
.
.
class BookCreateView(CreateView):
model = Book
fields = ['name', 'description', 'price']
template_name = 'add_book.html'
success_url = reverse_lazy('my_app:list_books')
def form_valid(self, form):
.
.
.
「models.py」で指定
from django.db import models
from django.urls import reverse_lazy
.
.
.
class Book(BaseModel):
.
.
.
def get_absolute_url(self):
return reverse_lazy('my_app:list_books')
「/my_app/add_book」にアクセスし、任意の値を入力して保存すると、一覧ページに遷移します。

↓

from django.db import models
from django.urls import reverse_lazy
.
.
.
class Book(BaseModel):
.
.
.
def get_absolute_url(self):
return reverse_lazy('my_app:list_books')
初期値の設定
「views.py」の修正
.
.
.
class BookCreateView(CreateView):
.
.
.
def get_initial(self, **kwargs):
initial = super(BookCreateView, self).get_initial(**kwargs)
initial['name'] = 'sample'
return initial
「/my_app/add_book」にアクセスしたときの表示

UpdateView
「forms.py」の修正
.
.
.
class BookUpdateForm(forms.ModelForm):
class Meta:
model = Book
fields = ['name', 'description', 'price']
def save(self, *args, **kwargs):
obj = super(BookUpdateForm, self).save(commit=False)
obj.save()
return obj
「views.py」の修正
.
.
.
from django.views.generic.edit import (
CreateView,
UpdateView
)
.
.
.
class BookUpdateView(UpdateView):
model = Book
template_name = 'update_book.html'
form_class = forms.BookUpdateForm
def get_success_url(self):
return reverse_lazy('my_app:list_books')
パスの追加
from django.urls import path
from .views import BookCreateView, BookDetailView, BookListView, BookUpdateView, IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
path('detail_book/<int:pk>', BookDetailView.as_view(), name='detail_book'),
path('list_books', BookListView.as_view(), name='list_books'),
path('add_book', BookCreateView.as_view(), name='add_book'),
path('edit_book/<int:pk>', BookUpdateView.as_view(), name='edit_book'),
]
HTMLファイルの作成
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="更新">
</form>
{% endblock %}
「book_list.html」の修正
{% extends 'base.html' %}
{% block content %}
<p><a href="{% url 'my_app:add_book' %}">データ追加</a></p>
<table class="table">
<tbody>
{% for object in object_list %}
<tr>
<td>名前: <a href="{% url 'my_app:detail_book' object.id %}">{{ object.name }}</a></td>
<td>金額: {{ object.price }}</td>
<td><a href="{% url 'my_app:edit_book' object.id %}">編集</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

DeleteView
「views.py」の修正
.
.
.
from django.views.generic.edit import (
CreateView,
DeleteView,
UpdateView
)
.
.
.
class BookDeleteView(DeleteView):
model = Book
template_name = 'delete_book.html'
success_url = reverse_lazy('my_app:list_books')
パスの追加
from django.urls import path
from .views import BookCreateView, BookDeleteView, BookDetailView, BookListView, BookUpdateView, IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
path('detail_book/<int:pk>', BookDetailView.as_view(), name='detail_book'),
path('list_books', BookListView.as_view(), name='list_books'),
path('add_book', BookCreateView.as_view(), name='add_book'),
path('edit_book/<int:pk>', BookUpdateView.as_view(), name='edit_book'),
path('delete_book/<int:pk>', BookDeleteView.as_view(), name='delete_book'),
]
HTMLファイルの作成
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
<p>{{ object.name }}を削除しますか?</p>
<input type="submit" value="削除">
</form>
{% endblock %}
「book_list.html」の修正
{% extends 'base.html' %}
{% block content %}
<p><a href="{% url 'my_app:add_book' %}">データ追加</a></p>
<table class="table">
<tbody>
{% for object in object_list %}
<tr>
<td>名前: <a href="{% url 'my_app:detail_book' object.id %}">{{ object.name }}</a></td>
<td>金額: {{ object.price }}</td>
<td><a href="{% url 'my_app:edit_book' object.id %}">編集</a></td>
<td><a href="{% url 'my_app:delete_book' object.id %}">削除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

FormView
「views.py」の修正
.
.
.
from django.views.generic.edit import (
CreateView,
DeleteView,
FormView,
UpdateView
)
.
.
.
class BookFormView(FormView):
template_name = 'form_book.html'
form_class = forms.BookForm
success_url = reverse_lazy('my_app:list_books')
def form_valid(self, form):
if form.is_valid():
form.save()
return super(BookFormView, self).form_valid(form)
パスの追加
from django.urls import path
from .views import BookCreateView, BookDeleteView, BookDetailView, BookFormView, BookListView, BookUpdateView, IndexView, HomeView
app_name = 'my_app'
urlpatterns = [
path('index', IndexView.as_view(), name='index'),
path('home/<name>', HomeView.as_view(), name='home'),
path('detail_book/<int:pk>', BookDetailView.as_view(), name='detail_book'),
path('list_books', BookListView.as_view(), name='list_books'),
path('add_book', BookCreateView.as_view(), name='add_book'),
path('edit_book/<int:pk>', BookUpdateView.as_view(), name='edit_book'),
path('delete_book/<int:pk>', BookDeleteView.as_view(), name='delete_book'),
path('book_form', BookFormView.as_view(), name='book_form'),
]
HTMLファイルの追加
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="保存">
</form>
{% endblock %}
「/my_app/book_form」にアクセス後、値を入力して保存すると正常に反映されます。

RedirectView
基本的な使い方
「urls.py」で使用
「urls.py」の修正
.
.
.
from django.views.generic.base import RedirectView
urlpatterns = [
.
.
.
path('google', RedirectView.as_view(url='https://google.co.jp'), name='google'),
]
「/my_app/google」にアクセスすると、グーグルのページにリダイレクトされます。
「views.py」で使用
「views.py」の修正
.
.
.
from django.views.generic.base import (
RedirectView, View, TemplateView
)
.
.
.
class BookRedirectView(RedirectView):
url = 'https://google.co.jp'
パスの追加
from django.urls import path
from .views import BookCreateView, BookDeleteView, BookDetailView, BookFormView, BookListView, BookRedirectView, BookUpdateView, IndexView, HomeView
.
.
.
urlpatterns = [
.
.
.
path('book_redirect_view', BookRedirectView.as_view(), name='book_redirect_view'),
]
「/my_app/book_redirect_view」にアクセスすると、グーグルのページにリダイレクトされます。
URLパラメータの使用
「views.py」の修正
.
.
.
class BookRedirectView(RedirectView):
def get_redirect_url(self, *args, **kwargs):
if 'pk' in kwargs:
return reverse_lazy('my_app:detail_book', kwargs={'pk': kwargs['pk']})
return reverse_lazy('my_app:list_books')
パスの追加
.
.
.
path('book_redirect_view', BookRedirectView.as_view(), name='book_redirect_view'),
path('book_redirect_view/<int:pk>', BookRedirectView.as_view(), name='book_redirect_view'),
「/my_app/book_redirect_view」にアクセスすると一覧ページに、
「/my_app/book_redirect_view/<id>」にアクセスすると詳細ページにリダイレクトされます。
SuccessMessageMixin
「update_book.html」の修正
{% extends 'base.html' %}
{% block content %}
{% if messages %}
{% for message in messages %}
{{ message.message }}
{% endfor %}
{% endif %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="更新">
</form>
<br>
<a href="{% url 'my_app:list_books' %}">一覧ページへ</a>
{% endblock %}
静的なメッセージ
「views.py」の修正
.
.
.
from django.contrib.messages.views import SuccessMessageMixin
.
.
.
class BookUpdateView(SuccessMessageMixin, UpdateView):
model = Book
template_name = 'update_book.html'
form_class = forms.BookUpdateForm
success_message = '更新しました'
def get_success_url(self):
return reverse_lazy('my_app:edit_book', kwargs={'pk': self.object.id})
.
.
.

動的なメッセージ
「views.py」の修正
.
.
.
class BookUpdateView(SuccessMessageMixin, UpdateView):
.
.
.
def get_success_message(self, cleaned_data):
return cleaned_data.get('name') + 'を更新しました'
.
.
.

今回は以上になります。
ご覧いただきありがとうございました!
続きはこちら↓
コメント