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に当該記事のサンプルソースを公開しています。

