0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

webアプリ my-favorite-list フォーム機能

Posted at

フォーム機能

したこと:リレーション

ユーザー入力を管理する

  • フォームを定義
  • データベースにデータを保存
  • モデルと紐づけ
  • データのバリテーション(データの型が正しいかどうか)

流れ

forms.py → scripts.py → views.py → urls.py → html

役割

フォームの定義 -> 選択肢 -> 見た目 -> urlの設定 -> html(ユーザーの見た目)

forms.py

  • リレーションのフォームを定義
  • class metaでフォームで使うmodel, field, widgetを指定。
  • defでフォームの初期化
  • 編集の際はリレーションの情報を取得
#bookフォーム
class BookForm(forms.ModelForm):
	# 分類のチェックボックス
	types = forms.ModelMultipleChoiceField( #formsのデータベースモデルから複数選択できる
	
	queryset=BookType.objects.all(), #選択肢のリスト = BookTypeからすべてのデータ取得
	widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}), #見た目 = attrs(htmlの属性)はチェックボックス
	label='分類',  # タイトル「分類」に変更
	required = False, #空欄のままでもOK
	)
	# ジャンルのチェックボックス
	genres = forms.ModelMultipleChoiceField(
	queryset=BookGenre.objects.all(),
	widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
	label='ジャンル',  # 修正: 本来のタイトルへ
	required=False,
	)
	# 状態のチェックボックス
	statuses = forms.ModelMultipleChoiceField(
	queryset=BookStatus.objects.all(),
	widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
	label='状態',  # 修正: 本来のタイトルへ
	required = False,
	)
	# 評価のチェックボックス
	values = forms.ModelMultipleChoiceField(
	queryset=Value.objects.all(),
	widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
	label='評価',  # 修正: 本来のタイトルへ
	required=False,
	)

	class Meta:
	    model = Book
	    fields = ['title', 'author', 'designer', 'types', 'genres', 'series', 'statuses', 'values']
	    widgets = {
	        'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'タイトルを入力してください'}),
	        'author': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '著者名を入力してください'}),
	        'designer': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '絵師を入力してください'}),
	        'series': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '巻数を入力してください'}),
	    }

		def __init__(self, *args, **kwargs):
		    request = kwargs.pop('request', None)
		    super().__init__(*args, **kwargs)
		
		    if request and request.path == '/book/search/':
		        self.fields.pop('series')
		
		    if self.instance and self.instance.pk:  # 編集モードの場合
		        # ManyToManyFieldの初期値を設定
		        self.fields['types'].initial = self.instance.type.all()
		        self.fields['genres'].initial = self.instance.genre.all()
		        self.fields['statuses'].initial = self.instance.status.all()
		        self.fields['values'].initial = self.instance.value.all()

scripts.py

  • for in []で選択肢を作る
  • 保存:model名.objects.get_or_create(name=name)
#Valueのデータ登録

for name in ['SS', 'S', 'A', 'B', 'C', 'D']:
	Value.objects.get_or_create(name=name)

#BookTypeのデータ登録

for name in ['小説', 'ライトノベル', '漫画', 'ビジネス本', 'お金']:
	BookType.objects.get_or_create(name=name)

#BookGenreのデータ登録

for name in ['推理・ミステリー', '青春', '恋愛', 'SF(サイエンスフィクション)', 'ファンタジー',
'ホラー', '経済', '政治', '歴史・時代', 'ミリタリー', '児童', '官能']:
	BookGenre.objects.get_or_create(name=name)

#BookStatusのデータ登録

for name in ['未読', '読書中', '読了', '購入済み', '気になる']:
	BookStatus.objects.get_or_create(name=name)

views.py

  • 選択肢1:int:pk等の場合、pkをコードで受け取っている場合勝手にurls.pyで解析してくれる
  • 選択肢2:新規作成
  • リクエストがある場合:保存 -> book_list(一覧ページに飛ぶ)
  • リクエストがない場合:fieldの情報を追加
  • render(book_formのページに情報を渡す)
def book_form(request, pk=None):
	if pk:  # pkが指定されている場合、編集モード
		book = get_object_or_404(Book, pk=pk)  #urls.pyでpkを解析してくれる
		form = BookForm(instance=book)
	else:  # pkがない場合、新規作成モード
		book = None
		form = BookForm()
		
	if request.method == 'POST':  # POSTリクエストの場合、フォームを保存
    form = BookForm(request.POST, instance=book) #フォームにPOSTデータを関連づけ(結びつけ)
    if form.is_valid():
        print(form.cleaned_data)
        book = form.save(commit=False) #インスタンス作成
        book.save() #データベースに保存
        form.save_m2m() #manytomanyfiledの関連データを保存 (今回はできなかった)

        # ManyToManyFieldに手動で関連付けを追加
        book.type.set(form.cleaned_data.get('types', []))
        book.genre.set(form.cleaned_data.get('genres', []))
        book.status.set(form.cleaned_data.get('statuses', []))
        book.value.set(form.cleaned_data.get('values', []))

        return HttpResponseRedirect(reverse('book_list'))  # リダイレクト

# 各フィールドの情報を追加
	field_data = []
	for field in form:
	    field_data.append({
	        'field': field,
	        'is_checkbox': isinstance(field.field.widget, forms.CheckboxSelectMultiple)  # チェックボックス判定(ラジオボタンやドロップダウンリストにも必要)
	    })

# テンプレートに渡す
	return render(request, 'myapp/book_form.html', {'field_data': field_data})

urls.py

  • 新しいページ
  • 編集ページ
path('book/form/', views.book_form, name='book_form'),
path('book/form/int:pk/', views.book_form, name='book_edit'),
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?