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

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

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

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

Python

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

Q&A

0回答

1386閲覧

modelformsetの更新と保存に関して

ktg_st

総合スコア33

Django

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

Python

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

0グッド

0クリップ

投稿2020/05/14 15:59

編集2020/05/17 08:38

参考ページ⇒https://narito.ninja/blog/detail/126/

カレンダーにスケジュールを保存できるようにしたく勉強中ですが、行き詰まりご助力お願いします。

やりたいこと:
下記コードだと、各日に予定を入力する新規フォームが設置されていますが、予定を保存すると更に新規フォームが追加されます。
予定未保存⇒新規フォームのみ  予定保存済⇒新規フォーム、更新フォーム
って感じです。
予定未保存⇒新規フォームのみ  予定保存済⇒更新フォーム
と変更したいのですが、どうすればいいのか分かりません。

説明下手ですいません。

下記画像

イメージ説明

mixins.py class MonthWithFormsMixin(MonthCalendarMixin): """スケジュール付きの、月間カレンダーを提供するMixin""" def get_month_forms(self, start, end, days): """それぞれの日と紐づくフォームを作成する""" lookup = { # '例えば、date__range: (1日, 31日)'を動的に作る '{}__range'.format(self.date_field): (start, end), 'user__pk': self.kwargs.get('user_pk'), } # 例えば、Schedule.objects.filter(date__range=(1日, 31日)) になる queryset = self.model.objects.filter(**lookup) days_count = len(days) FormClass = forms.modelformset_factory(self.model, self.form_class, extra=days_count,max_num=days_count) if self.request.method == 'POST': formset = self.month_formset = FormClass(self.request.POST, queryset=queryset) else: formset = self.month_formset = FormClass(queryset=queryset) # {1日のdatetime: 1日に関連するフォーム, 2日のdatetime: 2日のフォーム...}のような辞書を作る day_forms = {day: [] for day in days } # 各日に、新規作成用フォームを1つずつ配置 for empty_form, (date, empty_list) in zip(formset.extra_forms, day_forms.items()): empty_form.initial = {self.date_field: date} empty_list.append(empty_form) # スケジュールがある各日に、そのスケジュールの更新用フォームを配置 for bound_form in formset.initial_forms: instance = bound_form.instance date = getattr(instance, self.date_field) day_forms[date].append(bound_form) # day_forms辞書を、周毎に分割する。[{1日: 1日のフォーム...}, {8日: 8日のフォーム...}, ...] # 7個ずつ取り出して分割しています。 return [{key: day_forms[key] for key in itertools.islice(day_forms, i, i+7)} for i in range(0, days_count, 7)] def get_month_calendar(self): calendar_context = super().get_month_calendar() month_days = calendar_context['month_days'] month_first = month_days[0] month_last = month_days[-1] calendar_context['month_day_forms'] = self.get_month_forms( month_first, month_last, month_days ) calendar_context['month_formset'] = self.month_formset return calendar_context
views.py class MonthWithFormsCalendar(mixins.MonthWithFormsMixin, generic.View): """フォーム付きの月間カレンダーを表示するビュー""" template_name = 'app/month_with_forms.html' model = Schedule date_field = 'date' form_class = SimpleScheduleForm def get(self, request, **kwargs): context = self.get_month_calendar() context['user'] = get_object_or_404(User, pk=self.kwargs['user_pk']) return render(request, self.template_name, context) def post(self, request, **kwargs): context = self.get_month_calendar() user_pk = self.kwargs['user_pk'] user = get_object_or_404(User, pk=user_pk) context['user'] = user formset = context['month_formset'] if formset.is_valid(): instances = formset.save(commit=False) for schedule in instances: schedule.user = user schedule.save() return redirect('app:month_with_forms', user_pk=user_pk) return render(request, self.template_name, context)
models.py SUB_START = ( ('0', '✕'), ('1', '14'), ('2', '16'), ('3', '17'), ('4', '17.5'), ('5', '18'), ('6', '18.5'), ('7', '19'), ('8', '19.5'), ('9', '20'), ('10', '〇'), ) SUB_END = ( ('0', '✕'), ('1', '22'), ('2', '23'), ('3', '〇'), ) class Schedule(models.Model): """スケジュール""" user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='ユーザー', on_delete=models.SET_NULL, blank=True, null=True) start_time = models.CharField('開始時間', choices= SUB_START, max_length=50,blank=True,default="0") end_time = models.CharField('終了時間', choices= SUB_END, max_length=50,blank=True,default="0") date = models.DateField('日付') # created_at = models.DateTimeField('作成日', default=timezone.now) def __int__(self): return self.date
forms.py from django import forms from .models import Schedule class BS4ScheduleForm(forms.ModelForm): """Bootstrapに対応するためのModelForm""" class Meta: model = Schedule fields = ('start_time', 'end_time') widgets = { 'start_time': forms.TextInput(attrs={ 'class': 'form-control', }), 'end_time': forms.TextInput(attrs={ 'class': 'form-control', }), } def clean_end_time(self): start_time = self.cleaned_data['start_time'] end_time = self.cleaned_data['end_time'] if end_time <= start_time: raise forms.ValidationError( '終了時間は、開始時間よりも後にしてください' ) return end_time class SimpleScheduleForm(forms.ModelForm): """シンプルなスケジュール登録用フォーム""" class Meta: model = Schedule fields = ('start_time', 'end_time', 'date') 'date': forms.HiddenInput, }

code内のコメントは参考ページ内でのコメントです。

modelformset周りがよくわかっておらず、参考にできそうなサイトなどあれば教えて頂けると助かります。

よろしくお願いします。

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

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

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

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

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

xdolphinx

2020/05/16 06:20

情報が不足していて、このままだとなかなか回答が得られないと思います。 「参考ページ」がどういうものなのか、貼られている画像が何を指しているのか、追加を出さないようにしたい、というのが具体的にどういうことなのか、それぞれ説明が必要ではないでしょうか。 また関連するmodelやform, templateのコードも出したほうが良いと思います。
ktg_st

2020/05/17 08:28

ご指摘ありがとうございます。 編集します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問