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?

pkがないモデルインスタンスをModelFormを使って更新する

Last updated at Posted at 2025-06-01

前提

python:3.11
django:5.1

問題の概要

  • 対象となるモデルクラス(社員モデル):複合主キー制約を設定している & Primary keyがない
  • django側に「更新」であることを気付いてもらうためModelFormにinstanceを渡したいが、社員モデルにprimary keyが設定されていないためエラーになる(通常instanceを渡せばdjangoが「更新」であることを認識してくれてpkのバリデーションを突破できる)
  • ModelFormにinstanceを渡さないと、社員モデルの更新時にModelFormのバリデーションで複合主キー制約にひっかかり更新できない

実際のコード

mst_staff.py
class MstStaff(models.Model)
    staff_code = models.CharField()
    section = models.CharField()

    class Meta:
        constraints = [models.UniequeConstraint(fields=['staff_code', 'section'], name='unieque_staff')

form.py
class InputForm(forms.ModelForm):
    staff_code = models.CharField()
    section = models.CharField()

    class Meta:
        model = MstStaff
        fields = '__all__'
views.py
class UpdateView(View):
    def post(self, request):
        form = InputForm(request.POST)

        if form.is_valid():
            # ここでバリデーションを突破できない
            # update処理(省略)

複合主キー制約に引っかかる直接の原因

full_cleanメソッドのModel.validate_constraints() が呼び出されるため

解決策

ModelFormでfull_cleanメソッドをオーバーライドし、一意制約のバリデーションをスキップする

form.py
class InputForm(forms.ModelForm):
    # ...既存コード
    # 以下を追加
    def full_clean(self):
        self.instance.full_clean = lambda *args, **kqargs: None
        super().full_clean()

解説

  • Model バリデーション (Model.full_clean()) は、フォームバリデーションのステップ内でフォームの clean() メソッドが呼ばれたすぐ直後に実行されます ModelFormの検証

  • full_cleanメソッドではModel.clean_fields()、Model.clean()、 Model.validate_unique() (validate_unique が True の場合)、そして Model.validate_constraints() (validate_constraints が True の場合) をこの順序で呼び出し、4 つ全てのステージでのエラーを含む message_dict 属性を持つ ValidationError を発生させます。 full_clean()Model.validate_unique()

  • その為、ModelFormクラスでfull_cleanメソッドを無効化して、解決しました

備考

  • モデルクラスにpkをつければいいのでは?と言われると思いますが、システム要件的にそれは出来ず。。
  • フォームで複合主キー制約のバリデーションが必要であれば、cleanメソッドを手動で追加すればいいと思います
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?