質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2792閲覧

【Django】テンプレートから親子関係のモデルを作成するには?

退会済みユーザー

退会済みユーザー

総合スコア0

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/04/01 05:40

編集2020/04/01 05:43

前提・実現したいこと

現在、Djangoチュートリアルを終えたのでそのまま、下の画像のadminページのように、クライアント側がChoiceを自由に増やせるようなフォームをtemplate内でつくりたいと考えています。

イメージ説明

しかし、うまいQuestionモデルとChoiceモデルの紐づけ方が分からず、それぞれ別のクラスでフォームを作成しました。そのため、Choiceモデルが一つしか作成できません。(下に画像があります)

改善点あるいは全く違った方法でもよいので教えてください。

該当のソースコード

Python

1# model.py 2class Question(models.Model): 3 question_text = models.CharField(max_length=200) 4 pub_date = models.DateTimeField("date published") 5 close_date = models.DateTimeField( 6 default=timezone.datetime.now() + timezone.timedelta(weeks=1) 7 ) 8 sum_votes = models.IntegerField(default=0) 9 10 def __str__(self): 11 return self.question_text 12 13class Choice(models.Model): 14 question = models.ForeignKey(Question, on_delete=models.CASCADE) 15 choice_text = models.CharField(max_length=200) 16 votes = models.IntegerField(default=0) 17 18 def __str__(self): 19 return self.choice_text

Python

1# form.py 2class QuestionForm(forms.ModelForm): 3 class Meta: 4 model = Question 5 fields = ("質問文",) 6 7 8class ChoiceForm(forms.ModelForm): 9 class Meta: 10 model = Choice 11 fields = ("選択肢",)

Python

1# view.py 2def question_create(request): 3 if request.method == "POST": 4 form1 = QuestionForm(request.POST) 5 form2 = ChoiceForm(request.POST) 6 if form1.is_valid() and form2.is_valid(): 7 question = form1.save(commit=False) 8 question.pub_date = timezone.now() 9 question.close_date = timezone.datetime.now() + timezone.timedelta(weeks=1) 10 question.save() 11 choice = form2.save(commit=False) 12 question.choice_set.add(choice, bulk=False) 13 question.save() 14 return redirect("polls:detail", pk=question.id) 15 else: 16 form1 = QuestionForm() 17 form2 = ChoiceForm() 18 19 context = { 20 "form1": form1, 21 "form2": form2, 22 } 23 return render(request, "polls/create/index.html", context)

html

1<!-- templates/polls/create/index.html --> 2<form method="POST">{% csrf_token %} 3 {{ form1.as_p }} 4 {{ form2.as_p }} 5 <button type="submit">Save</button> 6</form>

↓結果(Choiceを自由に増やせるようにしたい)
イメージ説明
###バージョン
Django 3.0.4

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2020/04/01 06:58

テンプレート側でループするような構成を検討してみてはいかがでしょうか
退会済みユーザー

退会済みユーザー

2020/04/01 08:15

回答ありがとうございます。 テンプレートでループするとなると、 1.テンプレートでformをN(クライアントが決めた値)個作成するということでしょうか。 2.form2にN個のChoiceFormをあてるということでしょうか。 どちらも具体的な方法が分からないので教えていただきたいです。 (一回一回Saveして追加する方法は避けたいです)
t_obara

2020/04/01 10:07

HTML側をどのように表現するかわからないということでしょうか? チュートリアルでも、質問リストを複数対応していますよね?それの応用です。
退会済みユーザー

退会済みユーザー

2020/04/01 13:01

処理が複雑なので結局、ModelFormではなく、FormでCharFieldを作成し、view.pyでChoiceモデルに代入するという方法をとりました。 ありがとうございました。
guest

回答2

0


投稿2020/04/01 13:29

編集2020/04/01 13:32
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

選択肢フォームは最大5個で、それが2個以上埋まってればモデルを生成するという方法をとりました。

Python

1# form.py 2class ChoiceForm(forms.Form): 3 choice1 = forms.CharField(label="選択肢1", max_length=200, required=True,) 4 choice2 = forms.CharField(label="選択肢2", max_length=200, required=True,) 5 choice3 = forms.CharField(label="選択肢3", max_length=200, required=False,) 6 choice4 = forms.CharField(label="選択肢4", max_length=200, required=False,) 7 choice5 = forms.CharField(label="選択肢5", max_length=200, required=False,)

Python

1# view.py 2def question_create(request): 3 if request.method == "POST": 4 form1 = QuestionForm(request.POST) 5 form2 = ChoiceForm(request.POST) 6 if form1.is_valid() and form2.is_valid(): 7 question = form1.save(commit=False) 8 question.pub_date = timezone.now() 9 question.close_date = timezone.datetime.now() + timezone.timedelta(weeks=1) 10 question.save() 11 12 question.choice_set.create( 13 choice_text=form2.cleaned_data.get("choice1"), votes=0 14 ) 15 question.choice_set.create( 16 choice_text=form2.cleaned_data.get("choice2"), votes=0 17 ) 18 if form2.cleaned_data.get("choice3") != "": 19 question.choice_set.create( 20 choice_text=form2.cleaned_data.get("choice3"), votes=0 21 ) 22 if form2.cleaned_data.get("choice4") != "": 23 question.choice_set.create( 24 choice_text=form2.cleaned_data.get("choice4"), votes=0 25 ) 26 if form2.cleaned_data.get("choice5") != "": 27 question.choice_set.create( 28 choice_text=form2.cleaned_data.get("choice5"), votes=0 29 ) 30 31 question.save() 32 return redirect("polls:_votes") 33 else: 34 form1 = QuestionForm() 35 form2 = ChoiceForm() 36 37 context = { 38 "form1": form1, 39 "form2": form2, 40 } 41 return render(request, "polls/create/index.html", context)

html

1<form method="POST">{% csrf_token %} 2 {{ form1.as_p }} 3 <hr> 4 {{ form2.choice1.label }}:{{ form2.choice1 }} 5 <hr> 6 {{ form2.choice2.label }}:{{ form2.choice2 }} 7 <hr> 8 {{ form2.choice3.label }}:{{ form2.choice3 }} 9 <hr> 10 {{ form2.choice4.label }}:{{ form2.choice4 }} 11 <hr> 12 {{ form2.choice5.label }}:{{ form2.choice5 }} 13 <hr> 14 <button type="submit">Save</button> 15</form>

投稿2020/04/01 13:03

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問