teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

コードに `else` が欠けていたのを追加しました。

2018/11/02 12:18

投稿

gh640
gh640

スコア1407

answer CHANGED
@@ -46,8 +46,8 @@
46
46
  selected_foods = form.cleaned_data["food"]
47
47
  Food.objects.create(food=','.join(selected_foods))
48
48
  # return redirect(to='/hello/food')
49
-
49
+ else:
50
- form = FoodForm()
50
+ form = FoodForm()
51
51
  params = {
52
52
  'form': form,
53
53
  }

1

追記 2018/11/01 21:43: の部分を追記しました。

2018/11/02 12:18

投稿

gh640
gh640

スコア1407

answer CHANGED
@@ -17,4 +17,57 @@
17
17
 
18
18
  また、少し古くて Django 2.x に対応していないかもしれませんが(ググって見つけただけなので、動作確認していません)、次の使えそうなパッケージ等もあるようです。
19
19
 
20
- - https://github.com/goinnn/django-multiselectfield
20
+ - https://github.com/goinnn/django-multiselectfield
21
+
22
+ 追記 2018/11/01 21:43:
23
+
24
+ 以下、 2018/11/01 19:12 にいただいたコメントに対する回答です。
25
+
26
+ > Food.objects.create(food=',',join(form.cleaned_data["food"]))を書いて実行すると、
27
+ > 下記のエラーメッセージが出てしまいます。
28
+ > 'Food' object has no attribute 'cleaned_data'
29
+
30
+ `cleaned_data` は `Form` インスタンスのアトリビュートなのですが、そのエラーが出るということは `Food` のインスタンスに対して `cleaned_data` アトリビュートにアクセスしようとされているのだと思います。そうではないので、以下読み進めてください。
31
+
32
+ > cleaned_dataという処理をやっていないためだと思います。上記に示したコードで書き換えると、どのようなコードになりますでしょうか?
33
+
34
+ `cleaned_data` は `Form.is_valid()` を呼び出して成功したときにセットされるアトリビュートです。ですので、通常のライフサイクルでは `form.is_valid()` が `True` だったときに利用するものです。詳しくは公式のドキュメントの次の場所をご覧ください:
35
+
36
+ - https://docs.djangoproject.com/en/2.1/ref/forms/api/#accessing-clean-data
37
+
38
+ 「 上記に示したコードで書き換えると、どのようなコードになりますでしょうか? 」への回答としては、次のようなイメージになるでしょうか(なるべく原形を残すように努めました)。
39
+
40
+ ```python
41
+ # views.py:
42
+ def foodsettei(request):
43
+ if request.method == 'POST':
44
+ form = FoodForm(request.POST)
45
+ if form.is_valid():
46
+ selected_foods = form.cleaned_data["food"]
47
+ Food.objects.create(food=','.join(selected_foods))
48
+ # return redirect(to='/hello/food')
49
+
50
+ form = FoodForm()
51
+ params = {
52
+ 'form': form,
53
+ }
54
+
55
+ return render(request, 'hello/food.html', params)
56
+ ```
57
+
58
+ そして、申し訳ありません、最初に回答させていただいたときに気づかなかったのですが、 `FoodForm` の方も少し変更していただく必要があります。ウィジェットに `CheckboxSelectMultiple` を使うのであれば、 `ChoiceField` だとバリデーション(つまり `form.is_valid()` )が通らなくなるので、代わりに `MultipleChoiceField` を使用してみてください。
59
+
60
+ ```python
61
+ # forms.py:
62
+ class FoodForm(forms.Form):
63
+ FOOD_CHOICES = [("りんご", "りんご"), ("バナナ", "バナナ"), ("シャケ", "シャケ")]
64
+
65
+ food = forms.MultipleChoiceField(
66
+ label='食べ物',
67
+ widget=forms.CheckboxSelectMultiple,
68
+ choices=FOOD_CHOICES,
69
+ required=True,
70
+ )
71
+ ```
72
+
73
+ これで私の手元では正しく動いたのですが、いかがでしょうか。ご参考になれば幸いです。