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

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

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

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

12045閲覧

Django CheckboxSelectMultipleで、複数の選択を反映して、モデルに保存したい

MitMc

総合スコア34

Django

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

2クリップ

投稿2018/10/31 11:33

編集2018/10/31 13:33

Django CheckboxSelectMultipleで、複数の選択をリストとして、またはそれが不可能ならば、後で加工しやすい形(カンマ区切りの文字列等)でモデルに保存したいと考えています。

下記のコードを試し、複数のデータをチェックしても、1つのデータ("バナナ"だけ)しか入らないです。
どのようにしたら、複数選択した全てをリストとして、またはカンマ区切りの文字列等、後から加工しやすい形でモデルに保存できるでしょうか。

Django

1models.py 2 3class Food(models.Model): 4 class Meta: 5 db_table = 'Food' 6 7 food = models.CharField('食べ物', blank=True, max_length=100) 8

Django

1 2forms.py 3 4class FoodForm(forms.Form): 5 6 FOOD_CHOICES = [("りんご","りんご"),("バナナ","バナナ"),("シャケ","シャケ")] 7 8 food = forms.ChoiceField( 9 label='食べ物', 10 widget=forms.CheckboxSelectMultiple, 11 choices=FOOD_CHOICES, 12 required=True, 13 ) 14 15class FoodRecordForm(forms.ModelForm): 16 17 class Meta: 18 model = Food 19 fields = ['food'] 20 21

HTML

1<form action="{% url 'logicsettei' %}" method="post"> 2 {% csrf_token %} 3 {{form}} 4 5 <tr><td></td><td><input type="submit" value="登録する" id="test"></td></tr> 6</form>

django

1 2views.py 3 4def foodsettei(request): 5 if(request.method == 'POST'): 6 form = FoodForm() 7 obj = Food() 8 friend = FoodRecordForm(request.POST, instance=obj) 9 friend.save() 10 # return redirect(to='/hello/food') 11 12 else:' 13 form = FoodForm() 14 friend = '' 15 16 params = { 17 'form':form 18 } 19 20 return render(request,'hello/food.html',params) 21 22

環境
Python 3.6.5
Django'2.0.2'
macbook

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

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

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

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

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

guest

回答1

0

ベストアンサー

下記のコードを試し、複数のデータをチェックしても、1つのデータ("バナナ"だけ)しか入らないです。

view のコードを載せられていませんが、フォームで送信された値を保存する処理はどのようにされていますか?そこの処理をどのようにするかがポイントだと思いますので、そのコードをご共有いただくと具体的な回答がもらえやすくなると思います。

ざっくりとしたイメージとしては、あくまでも CharField をお使いになりたいのであれば、フォームで送信された値を join 等して Food.food に格納する形になるでしょうか。

イメージ:

python

1# views.py のフォーム送信データをオゾンする処理の一部: 2Food.objects.create(food=',',join(form.cleaned_data["food"]))

モデルの見直しも含めて考えられるのであれば、 FOOD_CHOICES で作られている選択肢を別のモデルとして作られて、 Food.food はそのモデルを参照する ManyToManyField として作られる形もありではないかと思います。そうすると Food に対する ModelForm がある程度自動的に複数選択機能を実現してくれるはずです。

また、少し古くて Django 2.x に対応していないかもしれませんが(ググって見つけただけなので、動作確認していません)、次の使えそうなパッケージ等もあるようです。

追記 2018/11/01 21:43:

以下、 2018/11/01 19:12 にいただいたコメントに対する回答です。

Food.objects.create(food=',',join(form.cleaned_data["food"]))を書いて実行すると、
下記のエラーメッセージが出てしまいます。
'Food' object has no attribute 'cleaned_data'

cleaned_dataForm インスタンスのアトリビュートなのですが、そのエラーが出るということは Food のインスタンスに対して cleaned_data アトリビュートにアクセスしようとされているのだと思います。そうではないので、以下読み進めてください。

cleaned_dataという処理をやっていないためだと思います。上記に示したコードで書き換えると、どのようなコードになりますでしょうか?

cleaned_dataForm.is_valid() を呼び出して成功したときにセットされるアトリビュートです。ですので、通常のライフサイクルでは form.is_valid()True だったときに利用するものです。詳しくは公式のドキュメントの次の場所をご覧ください:

「 上記に示したコードで書き換えると、どのようなコードになりますでしょうか? 」への回答としては、次のようなイメージになるでしょうか(なるべく原形を残すように努めました)。

python

1# views.py: 2def foodsettei(request): 3 if request.method == 'POST': 4 form = FoodForm(request.POST) 5 if form.is_valid(): 6 selected_foods = form.cleaned_data["food"] 7 Food.objects.create(food=','.join(selected_foods)) 8 # return redirect(to='/hello/food') 9 else: 10 form = FoodForm() 11 params = { 12 'form': form, 13 } 14 15 return render(request, 'hello/food.html', params)

そして、申し訳ありません、最初に回答させていただいたときに気づかなかったのですが、 FoodForm の方も少し変更していただく必要があります。ウィジェットに CheckboxSelectMultiple を使うのであれば、 ChoiceField だとバリデーション(つまり form.is_valid() )が通らなくなるので、代わりに MultipleChoiceField を使用してみてください。

python

1# forms.py: 2class FoodForm(forms.Form): 3 FOOD_CHOICES = [("りんご", "りんご"), ("バナナ", "バナナ"), ("シャケ", "シャケ")] 4 5 food = forms.MultipleChoiceField( 6 label='食べ物', 7 widget=forms.CheckboxSelectMultiple, 8 choices=FOOD_CHOICES, 9 required=True, 10 )

これで私の手元では正しく動いたのですが、いかがでしょうか。ご参考になれば幸いです。

投稿2018/10/31 12:15

編集2018/11/02 12:18
gh640

総合スコア1407

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

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

MitMc

2018/10/31 13:37

貴重な情報をありがとうございます。全て試してみます。
MitMc

2018/11/01 10:12

Food.objects.create(food=',',join(form.cleaned_data["food"]))を書いて実行すると、 下記のエラーメッセージが出てしまいます。 cleaned_dataという処理をやっていないためだと思います。上記に示したコードで書き換えると、どのようなコードになりますでしょうか? 'Food' object has no attribute 'cleaned_data'
gh640

2018/11/01 12:46

最後にいただいたコメントに対する返信を回答の末尾に追記しました。ご覧になってみてください。
MitMc

2018/11/01 15:43

ありがとうございます! 早速試してみます。
MitMc

2018/11/02 10:01

頂いたコードを参考に自分のプログラムに適用し、望んだ動作になりました。 forms.MultipleChoiceFieldと、','.join(....) の考えがとても助かりました。 どうもありがとうございました。
gh640

2018/11/02 12:20

そうですか!それはよかったです :) ChoiceField と CheckboxSelectMultiple の組み合わせは一見動くように見えるから要注意、でしたね。私も勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問