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

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

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

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

Python 3.x

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

10651閲覧

Djangoのフォームで、選択をフィルタリングする方法

am120sec

総合スコア14

Django

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

Python 3.x

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

3クリップ

投稿2018/03/28 23:15

編集2018/04/03 13:50

行き詰りました。

最初のプルダウンメニューで選択した項目を
次のプルダウンメニューに連動させたいです。
(admin管理サイトは使用しない)

Django

1#model.py 2 3class Create_type(models.Model): 4 name = models.CharField(max_length=20,unique=True) 5 def __str__(self): 6 return self.name 7 8class Genre(models.Model): 9 name = models.CharField(max_length=20,unique=True) 10 create_type = models.ManyToManyField(Create_type) 11 def __str__(self): 12 return self.name 13 14class Title_Post(models.Model): 15 title = models.CharField(unique=True) 16 create_type = models.ForeignKey(Create_type,blank=false) 17 genre = models.ManyToManyField(Genre,blank=True) 18

以下のサイトを参考にForm.pyを作成しました。
https://stackoverflow.com/questions/291945/how-do-i-filter-foreignkey-choices-in-a-django-modelform

Django

1#form.py 2 3class Title_Form(forms.ModelForm): 4 class Meta: 5 model = Title_Post 6 fields = ('title','create_type','genre') 7 8 def __init__(self, *args, **kwargs): 9 super(Title_Form, self).__init__(*args, **kwargs) 10 self.fields['genre'].queryset = Genre.objects.filter( 11 type=self.instance.type) 12

Django

1#view.py 2def title_new(request): 3 if request.method == "POST": 4 f = Title_Form(request.POST,request.FILES) 5 if f.is_valid(): 6 post = f.save(commit=False) 7 post.published_date = timezone.now() 8 post.save() 9 f.save_m2m() 10 return redirect('app:title', pk=post.pk) 11 else: 12 f = Title_Form() 13 return render(request, 'app/title_edit.html', {'form':f})
小説映画アニメ
SFSFSF
ホラーホラーホラー
3D3D

イメージ的には
Type(小説、映画、アニメ)があって、
Genre(SF、ホラー、3D)等のジャンルがあり、
フォーム上で小説を選択した場合、genreのリストでは「3D」を選択できないようにしたいです。
表示しないという動作はJavascriptで記述できたのですが、Javascriptを無効にした場合、不正な入力がされてしまうと思うので、Django側のModelやFormで入力をエラーとしたいです。

現状は、そもそもGenreに値が表示されません・・・

イメージ説明

何卒、よろしくお願いいたします・・

tachikoma👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

とりえあえず、全部選択肢にでるように
formの__init__なしにしましょう。

それからTitle_Formのcleanをオーバーライドしましょう
cleanのoverride例
値がおかしかったらValidationErrorをraiseして、
あってたら特に何もしなくていいです。

投稿2018/03/29 16:17

kokardy

総合スコア781

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

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

am120sec

2018/03/30 04:41

途中ですが、選択肢は表示されるようになりました。 次に値の検証ですが、ManyToManyでリレーションされたクラスのフィールドを取得する方法が解りません。 参考資料でも良いのでヒントを頂けないでしょうか。 class Title_Form(forms.ModelForm): class Meta: model = Title_Post fields = ('title','create_type','genre') def clean(self): cleaned_date = super().clean() genre = cleaned_date.get("genre") create_type = cleaned_date.get("create_type") genre_create_type = #ここです if genre and create_type: if genre.create_type != create_type: raise form.balidationError( "そのジャンルは使用できません" )
kokardy

2018/03/30 16:49

ちょっといま確認できませんけど、 cleaned_data.get("genre")ってやったらQuerySetが返ってきませんか? forで回せるのではないかと。
am120sec

2018/04/03 00:02

その前にcleaned_dataが上手く動いて無いようでした・・ 簡単なcleaned_dataで作ってみてもダメです・・。 class Title_Form(forms.ModelForm): volume = forms.IntegerField(required=False) class Meta: model = Title_Post fields = ('title','create_type','genre','volume') def clean_volume(self): volume = self.cleaned_date["volume"] if not 1 <= volume <= 10: raise forms.ValidationError(u"1-10の範囲で入力してください") return volume これでフォームをSAVEすると、'Title_Form' object has no attribute 'cleaned_date'エラーが出てしまいます。 view.pyがおかしいのでしょうか・・。
kokardy

2018/04/03 13:43 編集

書くところ間違えました…… 回答は消せないのかな "cleaned_data"のタイプミスと思われます。
am120sec

2018/04/03 13:53

私のほうからは削除できませんでした。 "cleaned_data"でいけました・・・・・・・・・! 中学生からやり直してきます(´;ω;`)
kokardy

2018/04/03 13:58

スマホからだと見つけられなかったんですが、 PCで開いたら削除リクエストの場所みつけました。 お騒がせしました。
guest

0

やり方が正しいかどうかは置いておいて、とりあえず動く物ができましたので報告です。

genre_filter = genre.filter(create_type__name = create_type)

アンダースコアが2つ入っているのはcreate_typeのnameフィールドを指定するためらしいです。

ご指摘ありましたら是非ともお願いします。

Django

1#form.py 2class Title_Form(forms.ModelForm): 3 volume = forms.IntegerField(required=False) 4 class Meta: 5 model = Title_Post 6 fields = ('title','create_type','genre') 7 8 9 def clean(self): 10 cleaned_date = super().clean() 11 genre = self.cleaned_data.get("genre") 12 create_type = self.cleaned_data.get("create_type") 13 14 if genre and create_type: 15 genre_filter = genre.filter(create_type__name = create_type) 16 if len(genre_filter) == 0: 17 raise forms.ValidationError( 18 "選択されたジャンルはタイプと関連性がないため使用できません" 19 )

投稿2018/04/05 01:21

am120sec

総合スコア14

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問