LoginSignup
0
1

More than 1 year has passed since last update.

【Django】ModelFormSetでフォームの初期値を設定する方法

Last updated at Posted at 2022-12-06

はじめに

ModelFormSetに初期値を設定する方法を説明します。

ModelFormは1つのテンプレートに1つしか作成することができません。
複数のModelFormを同時に作成する場合は、ModelFormSetを使用します。

概要

ModelFormSetに初期値を設定する方法は様々ありますが
こちらでは、ModelFormSetのインスタンス化時に初期値を設定する方法を説明します。
ビューからフォームに値を渡す方法も説明しているため、動的に初期値を設定することも可能です。
それでは、さっそく実装していきましょう。

説明

モデル

以下のモデル、フォーム、ビューを例に説明します。

apps/memo/models.py
from django.db import models

class Memo(models.Model):
    title = models.CharField('タイトル', max_length=20)
    text = models.TextField('内容')

    def __str__(self):
        return self.title

ビュー

画面にModelFormSetを表示するために、contextにインスタンスを渡します。

apps/memo/views.py
from django.views.generic import TemplateView
from apps.memo.models import Memo


class MemoView(TemplateView):
    model = Memo
    template_name = "memo/template.html"

    def get_context_data(self, *args, **kwargs, request)
        context = super().get_context_data(self, *args, **kwargs, request)
        context['formset'] = MemoFormSet()

        return context

フォーム

BaseMemoFormSetのinit関数で、初期値を設定できます。
self.querysetに代入された値が初期値となります。
そのため、Noneを代入した場合は初期値なしということになります。
self.querysetの値を上書きしない場合は、modelformset_factoryの第一引数で指定したモデルのすべてのデータが初期値に設定されます。ご注意ください。

apps/memo/forms.py
from django.forms import ModelForm, BaseModelFormSet, modelformset_factory
from apps.memo.models import Memo

class MemoForm(ModelForm):
    class Meta:
        model = Memo
        fields = ('title', 'text')


class BaseMemoFormSet(BaseModelFormSet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 初期値を設定する
        self.queryset = None

MemoFormSet = modelformset_factory(Memo, Form=MemoForm, formset=BaseMemoFormSet)

初期値を設定する

①②の順番でModelFormSetに初期値を設定します。
①ビューからフォームに値を渡す
②フォームで値を受け取り、初期値を設定する

ログインユーザーに紐づくデータを初期値に持たせたい場合などに活用できます。
ビューからユーザーIDを渡して、フォームでユーザーIDに紐づくデータを初期値に設定する。
といったことが可能です。

ビュー

MemoFormSetインスタンス化時に、MemoViewからMemoFormSetに値を渡します。

apps/memo/views.py
from django.views.generic import TemplateView
from apps.memo.models import Memo
from apps.memo.forms import MemoFormSet


class MemoView(TemplateView):
    model = Memo
    template_name = "memo/template.html"

    def get_context_data(self, *args, **kwargs, request)
        context = super().get_context_data(self, *args, **kwargs, request)
        # MemoFormSetに値を渡す(key:'title', value:'test')
        context['formset'] = MemoFormSet('title'='test') 

        return context

フォーム

BaseMemoFormSetのinit関数内でMemoViewで渡された値を受け取ることができます。
以下のソースではMemoViewから渡された値を、初期値の取得の条件に使用しています。

apps/memo/forms.py
from django.forms import ModelForm, BaseModelFormSet, modelformset_factory
from apps.memo.models import Memo

class MemoForm(ModelForm):
    class Meta:
        model = Memo
        fields = ('title', 'text')


class BaseMemoFormSet(BaseModelFormSet):
    def __init__(self, *args, **kwargs):
        # MemoViewで渡した'test'を受け取る
        title = kwargs.pop('title')
        super().__init__(*args, **kwargs)
        # 初期値を設定する
        self.queryset = Memo.objects.filter(title__startswith=title)


MemoFormSet = modelformset_factory(Memo, Form=MemoForm, formset=BaseMemoFormSet)

参考

Django 公式サイト

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