web-dev-qa-db-ja.com

Django複数選択フィールド/チェックボックス複数選択

Djangoアプリケーションがあり、ユーザーのプロファイルに複数の選択チェックボックスを表示したい場合、それらは複数のアイテムを選択できるようになります。

これは私のmodels.pyの簡易版です:

from profiles.choices import SAMPLE_CHOICES

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True, verbose_name_('user'))
    choice_field = models.CharField(_('Some choices...'), choices=SAMPLE_CHOICES, max_length=50)

そして、私のフォームクラス:

class ProfileForm(forms.ModelForm):
    choice_field = forms.MultipleChoiceField(choices=SAMPLE_CHOICES, widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = Profile

そして私のviews.py:

if request.method == "POST":
    profile_form = form_class(request.POST, instance=profile)
    if profile_form.is_valid():
        ...
        profile.save()
return render_to_response(template_name, {"profile_form": profile_form,}, context_instance=RequestContext(request))

POSTは1つの値のみを送信していることがわかります。

choice_field u'choice_three' 

そして、ローカル変数パラメータはリストを送信しています:

[u'choice_one', u'choice_two', u'choice_three']

すべてのフォームフィールドが正しく表示されますが、POSTを送信するとエラーが発生します

パラメーター7のバインディングエラー-おそらくサポートされていないタイプ。

ビューで複数選択フィールドをさらに処理する必要がありますか?モデルフィールドタイプは正しいですか?ヘルプや参照は大歓迎です。

35
twampss

これを正しく機能させるには、プロファイルの選択肢をManyToManyFieldとして設定する必要があります。

そのため、モデルは次のようになります。

class Choices(models.Model):
  description = models.CharField(max_length=300)

class Profile(models.Model):
  user = models.ForeignKey(User, blank=True, unique=True, verbose_name='user')
  choices = models.ManyToManyField(Choices)

次に、データベースを同期し、利用可能なさまざまなオプションで選択肢をロードします。

これで、ModelFormは自動的にビルドされます...

class ProfileForm(forms.ModelForm):
  Meta:
    model = Profile
    exclude = ['user']

そして最後に、ビュー:

if request.method=='POST':
  form = ProfileForm(request.POST)
  if form.is_valid():
    profile = form.save(commit=False)
    profile.user = request.user
    profile.save()
else:
  form = ProfileForm()

return render_to_response(template_name, {"profile_form": form}, context_instance=RequestContext(request))

継承を含むいくつかの異なる方法でプロファイルを設定できることに注意してください。そうは言っても、これはあなたにとってもうまくいくはずです。

がんばろう。

34
Brant

ブラントのソリューションは完全に正しいですが、複数の選択チェックボックスとcommit=false。ここに私の解決策があります:

models.py

class Choices(models.Model):
    description = models.CharField(max_length=300)

class Profile(models.Model):
   user = models.ForeignKey(User, blank=True, unique=True, verbose_name_('user'))
   the_choices = models.ManyToManyField(Choices)

forms.py

class ProfileForm(forms.ModelForm):
    the_choices = forms.ModelMultipleChoiceField(queryset=Choices.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = Profile
        exclude = ['user']

views.py

if request.method=='POST':
    form = ProfileForm(request.POST)
    if form.is_valid():
        profile = form.save(commit=False)
        profile.user = request.user
        profile.save()
        form.save_m2m() # needed since using commit=False
    else:
        form = ProfileForm()

return render_to_response(template_name, {"profile_form": form}, context_instance=RequestContext(request))
15
twampss

Models.CharFieldは、いずれかの選択肢のCharField表現です。あなたが望むのは選択肢のセットです。これはDjango(まだ)で実装されていないようです。

あなたはcouldで多対多のフィールドを使用できますが、それは選択肢をデータベースに入れなければならないという欠点があります。ハードコードされた選択肢を使用したい場合、これはおそらくあなたが望むものではありません。

Django http://djangosnippets.org/snippets/1200/ にスニペットがありますdoesModelField MultipleChoiceField を実装して、問題を解決します。

13
Webthusiast

ManyToManyFieldは良い選択ではありません。いくつかのスニペットを使用してMultipleChoiceFieldを実装できます。 MultiSelectFieldコンマ区切りの値(フィールド+ FormField) しかし、それにはいくつかのバグがあります。そして、あなたは Django-multiselectfield をインストールすることができます。

2
wyx