DjangoのModelChoiceFieldの初期値を設定する方法
DjangoのModelChoiceFieldの初期値を設定する方法をご紹介します。
ここでは、プルダウンリストで初期値を設定する方法を例にとります。
目次
条件
- Django 2.1.7
- Python 3.7.0
実装
models.py
以下のようなモデルを考えます。
投稿者:投稿 = 1:N になるものとします。
from django.db import models from django.urls import reverse from django.contrib.auth.models import AbstractUser class CustomUser(AbstractUser): def __str__(self): return self.username + ":" + self.email class Post(models.Model): """投稿モデル""" class Meta: db_table = 'post' title = models.CharField(verbose_name='タイトル', max_length=255) text = models.CharField(verbose_name='内容', max_length=255, default='', blank=True) author = models.ForeignKey( 'search.CustomUser', on_delete=models.CASCADE, ) created_at = models.DateTimeField(verbose_name='登録日時', auto_now_add=True) updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True) def __str__(self): return self.title + ',' + self.text @staticmethod def get_absolute_url(self): return reverse('search:index')
urls.py
検索画面、登録画面、詳細画面を用意します。
本記事で主に使用するのは「登録画面」です。
# urls.py from django.urls import path from . import views app_name = 'search' urlpatterns = [ # 検索画面 path('', views.IndexView.as_view(), name='index'), # 登録画面 path('create/', views.CreateView.as_view(), name='create'), # 詳細画面 path('search/<int:pk>/', views.DetailView.as_view(), name='detail'),
forms.py
登録画面用のフォームを定義します。
# forms.py抜粋 from .models import Post from django import forms class PostForm(forms.ModelForm): class Meta: model = Post fields = ('title','text','author',)
views.py
以下はviews.pyの抜粋です。
ポイントはCreateViewクラスのget_form_kwargs()において、フォームに初期値を設定していることです。
# views.py抜粋 from django.views import generic from .models import Post from .forms import PostForm from django.shortcuts import reverse class CreateView(generic.CreateView): # 登録画面 model = Post form_class = PostForm def get_success_url(self): # 詳細画面にリダイレクトする。 return reverse('search:detail', kwargs={'pk': self.kwargs['pk']}) def get_form_kwargs(self, *args, **kwargs): form_kwargs = super().get_form_kwargs(*args, **kwargs) form_kwargs['initial'] = {'author': self.request.user} # フォームに初期値を設定する。 return form_kwargs class DetailView(generic.DetailView): # 詳細画面 model = Post template_name = 'search/detail.html'
template
post_form.html
登録画面用のテンプレートです。
{% extends 'base.html' %} {% load i18n static %} {% block content %} <div class="col-lg-6 offset-lg-3"> <h1>Registration</h1> <form method="post" enctype="multipart/form-data"> {% csrf_token %} {% if form.errors %} <p class="error-msg"> {% if form.errors.items|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %} </p> {% endif %} {{ form.title.errors }} <div class="form-group form-inline"> <label class="col-offset-1 col-3 control-label"> {{ form.title.label_tag }} </label> <div class=""> {{ form.title }} </div> </div> {{ form.text.errors }} <div class="form-group form-inline"> <label class="col-offset-1 col-3 control-label"> {{ form.text.label_tag }} </label> <div class=""> {{ form.text }} </div> </div> {% if user.is_superuser %} {{ form.author.errors }} <div class="form-group form-inline"> <label class="col-offset-1 col-3 control-label"> {{ form.author.label_tag }} </label> <div class=""> {{ form.author }} </div> </div> {% endif %} <div class="btn-toolbar justify-content-center" role="toolbar" aria-label="ボタングループのツールバー"> <div class="btn-group mr-2"> <a class="btn btn-primary w-150px" href="{% url 'search:index' %}" role="button">検索画面へ</a> </div> <div class="btn-group mr-2"> <input class="btn btn-success w-150px" type="submit" id="button" name="button" value="登録実行"> </div> </div> </form> </div> {% endblock %}
detail.html
詳細画面用のテンプレートです。
{% extends 'base.html' %} {% block content %} <div class="col-lg-6 offset-lg-3"> <h1>Detail</h1> {% if messages %} <ul class="messages"> {% for message in messages %} <li{% if message.tags %} class="{{ message.tags }}"{% endif %}> <h2 class="info-msg">{{ message }}</h2> </li> {% endfor %} </ul> {% endif %} <table class="table table-hover table-bordered"> <tbody> <tr> <th width="40%">タイトル</th> <td width="60%">{{ post.title }}</td> </tr> <tr> <th width="40%">内容</th> <td width="60%">{{ post.text }}</td> </tr> </tbody> </table> <div class="btn-toolbar justify-content-center" role="toolbar" aria-label="ボタングループのツールバー"> <div class="btn-group mr-2"> <a class="btn btn-primary w-150px" href="{% url 'search:index' %}" role="button">検索画面へ</a> </div> </div> </div> {% endblock %}
実行結果
フォームに初期値を渡さない場合
Autherのプルダウンリストが、未選択の状態で表示されます。
フォームに初期値を渡す場合
Autherのプルダウンリストが、初期値で渡した「ログインユーザー」が選択された状態で表示されます。
サンプルソース
GitHubに当該記事のサンプルソースを公開しています。