スポンサーリンク
概要
Djangoでフォーム入力をさせる際に、入力された値によるバリデーションとは別に、DBにアクセスして重複データが無いかチェックする事などがあるかと思います。
新規データの場合には、気にする必要がありませんが、更新データの場合にはDBから値を取り出す際に自分自身のデータは除外する必要があります。(ケースによります)
その際には、既存データの主キーとなるpkを取り出してクエリに渡さないといけません。
その際のpkの取得方法のメモです。
スポンサーリンク
スポンサーリンク
方法
下記のような開始日時と終了日時をデータとして持つModelを例に説明します。
下記のModelにはget_rangesといった、指定した範囲の時刻のデータを取り出すメソッドを定義します。
引数にはpkで特定のデータは除外できるようにします。
1 2 3 4 5 6 7 |
class WeeklyScheduleModel(models.Model): start_time = models.TimeField() end_time = models.TimeField() @classmethod def get_ranges(cls, pk, start_time, end_time): return WeeklyScheduleModel.objects.filter(start_time__gte=start_time, end_time__lte=end_time).exclude(pk=pk) |
上記のモデルに対応するModelFormを継承したフォームを定義します。
cleanメソッドをオーバーライドする事で、独自のバリデーションを実装します。
cleaned_dataから入力された値を取得できますが、pkに関してはinstance.pkから取得。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class WeeklyScheduleModelForm(forms.ModelForm): class Meta: model = models.WeeklyScheduleModel fields = { 'start_time', 'end_time'} def clean(self): start_time = self.cleaned_data['start_time'] end_time = self.cleaned_data['end_time'] if start_time >= end_time: raise forms.ValidationError("開始日時は終了日時より過去にする必要があります。") ranges = models.WeeklyScheduleModel.get_ranges(self.instance.pk, start_time, end_time) if ranges.count() > 0: raise forms.ValidationError("重複したスケジュールが存在します。") return self.cleaned_data |