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

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

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

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

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1765閲覧

[Django] formsetを用いてeditページのtemplate内で初期値が交互に表示されるようにしたい

kawataku

総合スコア3

Django

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

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/07/09 04:26

前提・実現したいこと

Djangoを用いて旅行の日程を作成するwebアプリを作成しているのですが、編集ページを作成して、前回入力していた部分は既に入力されている状態にしたいです。

一応、初期値として反映することはできているのですが、異なるformsetを交互に表示させるようにしたいです。

前提としまして、以下のような状態が旅行作成画面のデフォルトの状態になっておりまして、「観光地を追加」ボタンをクリックしたら、入力欄が追加されるようになる感じです。
デフォルト

発生している問題・エラーメッセージ

上が旅行作成ページの写真です。
旅行作成ページ
そして、下が上で作成したものを編集するページになります。
編集ページ

旅行作成ページと同じような形で編集ページも表示したいのですが、上手くいきません。

該当のソースコード

forms.py

Django

1class SpotForm(forms.ModelForm): 2 def __init__(self, *args, **kwargs): 3 super().__init__(*args, **kwargs) 4 5 class Meta: 6 model = Spot 7 fields = ('spot_name', 'spot_time', 'spot_cost') 8 widgets = { 9 'spot_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '観光地'}), 10 'spot_time': forms.DateTimeInput(attrs={'class': 'form-control smallDate', 'placeholder': '到着時間', 'autocomplete': 'off'}), 11 'spot_cost': forms.NumberInput(attrs={'class': 'form-control costs', 'placeholder': '滞在料金'}) 12 } 13 14class TransportForm(forms.ModelForm): 15 def __init__(self, *args, **kwargs): 16 super().__init__(*args, **kwargs) 17 18 class Meta: 19 model = Transport 20 fields = ('transport_name', 'transport_time', 'transport_fee') 21 widgets = { 22 'transport_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '移動手段'}), 23 'transport_time': forms.DateTimeInput(attrs={'class': 'form-control smallDate', 'placeholder': '乗る時間', 'autocomplete': 'off'}), 24 'transport_fee': forms.NumberInput(attrs={'class': 'form-control costs', 'placeholder': '料金'}) 25 }

views.py

Django

1 2@login_required(login_url='/make_trip/') 3def test(request): 4 SpotFormSet = forms.modelformset_factory( 5 Spot, form=SpotForm, extra=1 6 ) 7 TransportFormSet = forms.modelformset_factory( 8 Transport, form=TransportForm, extra=1 9 ) 10 spots = SpotFormSet(queryset=Spot.objects.none()) 11 transports = TransportFormSet(queryset=Transport.objects.none()) 12 13 if request.method == 'POST': 14 spot_form = SpotForm(request.POST) 15 transports = TransportFormSet(request.POST) 16 17 # 保存したtripの情報を取得 18 trip_id = Trip.objects.filter(group=group_id).first() 19 20 spot_save = spot_form.save(commit=False) 21 spot_save.trip = trip_id 22 spot_save.save() 23 24 spot = spots.save(commit=False) 25 for spot_db in spot: 26 spot_db.trip = trip_id 27 spot_db.save() 28 29 # transport用にspotの情報を取得する 30 spot_id = Spot.objects.filter(trip=trip_id) 31 print('spot_id:', spot_id) 32 transport = transports.save(commit=False) 33 for i in range(len(transport)): 34 transport[i].spot = spot_id[i] 35 transport[i].save() 36 37 return redirect(to='/make_trip/myPage') 38 39 params = { 40 'spots': spots, 41 'transports': transports 42 } 43 44 return render(request, 'make_trip/test.html', params) 45 46 47# 編集用のページを作成 48 49@login_required(login_url='/make_trip/') 50def test_edit(request, num): 51 spot_model = Spot.objects.filter(trip=trip_model.id) 52 transport_model = Transport.objects.filter(spot__in=spot_model) 53 SpotFormSet = forms.modelformset_factory( 54 Spot, form=SpotForm, extra=0 55 ) 56 TransportFormSet = forms.modelformset_factory( 57 Transport, form=TransportForm, extra=0 58 ) 59 60 # idがnumのtripを取得する 61 if request.method == 'POST': 62 # 更新時は既に親モデルと繋がっている状態で渡されるから、いちいち外部キーを取得する必要はない 63 spots = SpotFormSet(request.POST, queryset=spot_model) 64 transports = TransportFormSet(request.POST, queryset=transport_model) 65 66 spot = spots.save(commit=False) 67 for spot_db in spot: 68 spot_db.trip = trip_model 69 spot_db.save() 70 71 # transport用にspotの情報を取得する 72 spot_id = Spot.objects.filter(trip=trip_model) 73 print('spot_id:', spot_id) 74 transport = transports.save(commit=False) 75 for i in range(len(transport)): 76 transport[i].spot = spot_id[i] 77 transport[i].save() 78 79 return redirect(to='/make_trip/myPage') 80 81 # Getアクセス時の処理 82 else: 83 spots = SpotFormSet(queryset=spot_model) 84 transports = TransportFormSet(queryset=transport_model) 85 86 params = { 87 'spots': spots, 88 'transports': transports 89 } 90 return render(request, 'make_trip/edit.html', params)

spotもtransportもModelformsetを使用しておりまして、template内でそれぞれforを回して、初期値を設定していくようにしています。

また、一応補足としまして、trip_idなどは取得済みだと考えていただければ大丈夫です。

html

1<form action="" method="post"> 2 {% csrf_token %} 3 <div id="tranSpotDefault"> 4 <div id="tranSpot_formset"> 5 {{ transports.management_form }} 6 {% for transport in transports %} 7 <div class="row justify-content-end mb-5" id="input-transport-form-{{ forloop.counter0 }}"> 8 <div class="col-2"><h1 class="text-light"></h1></div> 9 <div class="col-3"> 10 {{ transport.transport_name }} 11 </div> 12 <div class="col-3"> 13 {{ transport.transport_time }} 14 </div> 15 <div class="col-3"> 16 {{ transport.transport_fee }} 17 </div> 18 </div> 19 {% endfor %} 20 {{ spots.management_form }} 21 {% for spot in spots %} 22 <div class="row mb-5" id="input-spot-form-{{ forloop.counter0 }}"> 23 <div class="col-4"> 24 {{ spot.spot_name }} 25 </div> 26 <div class="col-4"> 27 {{ spot.spot_time }} 28 </div> 29 <div class="col-4"> 30 {{ spot.spot_cost }} 31 </div> 32 </div> 33 {% endfor %} 34 </div> 35 </div> 36 <div id="tranSpot"></div> 37 <button class="btn btn-outline-success" type="button" id="addSpot">観光地を追加</button> 38 <div class="col-6 col-md-4 col-xl-3 col-xs-12 mx-auto"> 39 <button type="submit" class="btn btn-light btn-block border-0" style="background-color: rgba(191, 202, 63, 0.99);">完成!</button> 40 </div> 41</form>

試したこと

今回投稿したコードだと、template内でforが別々に回るので、こう

views.pyの中でtransportspotを一つのリストや辞書にまとめることによって、template内で交互にそれぞれを表示することができないかやってみたのですが、無理そうでした。
また、template内でrangelenを使って、インデックスを指定することに表示できないかやってみたのですが、こちらも無理そうでした。

補足情報(FW/ツールのバージョンなど)

Python v3.7.7
Visual Studio Code v1.53.2
MacOS Darwin x64 20.3.0
Django 3.0.4

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

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

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

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

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

guest

回答1

0

ベストアンサー

「django-boost」を使うとPythonの組み込み関数っぽいことをテンプレート上で使えるようになります。
導入方法はググって頂いて。

上記の場合ですとzip関数を使うと上手くいくかもしれません。

Python

1{% for transport, spot in transports|zip:spots %} 2 {{ transport.transport_name }} 3 {{ spot.spot_name }} 4{% endfor %}

のような書き方ができるようになります。
いかがでしょうか?

投稿2021/07/09 14:59

TechChuna

総合スコア86

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

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

kawataku

2021/07/11 02:23

ありがとうございます! できるようになりました!!!! 諦めかけていたので、本当に助かりました!!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問