1
1

More than 1 year has passed since last update.

Django Formクラスのprefixの紹介

Posted at

はじめに

DjangoでFormを使ったviewを作ってて以下のような不便を感じたことはありませんか?
「1つのviewに2つのFormを表示してるんだけど、同じname属性を持ったinputが2つできちゃって、POSTがわかりずらい」
こんな時に役に立つのが、Formのインスタンス作成時に指定できるprefixです

コードの紹介

サンプルとして定義したmodels.pyとforms.py

今回はModelFormでサンプルを示すので、事前にmodels.pyとそれに基づいたforms.pyを定義しますね

models.py
from django.db import models

# Create your models here.
class TestModel(models.Model):
    name = models.CharField(max_length=100)

class SampleModel(models.Model):
    name = models.CharField(max_length=100)
forms.py
class TestForm(forms.ModelForm):
    class Meta:
        model = models.TestModel
        fields = '__all__'

class SampleForm(forms.ModelForm):
    class Meta:
        model = models.SampleModel
        fields = '__all__'

prefixを使わないviewsの書き方

views.py
class CreateTest(generic.CreateView):
    template_name = 'reg.html'
    form_class = forms.TestForm
    model = models.TestModel

    def post(self, request, *args, **kwargs):
        print(request.POST)
        return super().post(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx['form2'] = forms.SampleForm()

        return ctx

このviewを以下のtemplateで表示してみます

reg.html
<form method="post">
    {{ form }}
    {{ form2 }}
    <button>submit!</button>
</form>

以下のようになります
image.png
ふたつのInput要素のname属性が重複してしまっているのがわかりますね
2つのInput要素には「ほげ」「ふが」と順に入力してsubmitボタンで送信してみます

以下のようにとれました
※csrf_tokenの中身は長いので省略してます

<QueryDict: {'csrfmiddlewaretoken': [''], 'name': ['ほげ', 'ふが']}>

これだとどっちのFormにどっちを渡せばいいかわからないですよね。templateで定義している順番でリストも構成されているので、requesr.POST['name'][0]と指定してあげてもいいですが、またinput要素が追加されてが順番が変わってしまうかもしれません

prefixを使ったviewsの書き方

こんなときは「name属性の値を変えてしまいたい」と思いますよね。けどModelFormを使っているので、簡単に変えることはできません
そんなときに役に立ちそうなのがprefixです

views.py
class CreateTest(generic.CreateView):
    template_name = 'reg.html'
    form_class = forms.TestForm
    model = models.TestModel
    success_url = 'qiita'

    def post(self, request, *args, **kwargs):
        print(request.POST)
        return super().post(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx['form2'] = forms.SampleForm(prefix='test')

        return ctx

この状態で構成されるtemplateを見てみましょう
image.png

form2のinput要素のnameが[prefixに指定した文字列-元のname属性名]となりました
これによりrequest.POSTで受け取ると別々の値として受け取ることができます

<QueryDict: {'csrfmiddlewaretoken': [''], 'name': ['ほげ'], 'test-name': ['ふが']}>

結言

prefixを使うと重複した名前をもったinput要素をうまい感じに管理できました

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