Djangoはあなたが思うように動作しません



フレームワークが提供するパンのリストを読むと、それらの意味が想像できます。 グッズのドキュメントを読むときは、全体としてすべてが本当に私が考えていた方法であることを確認します。 コードを書くとき、私はタオを理解します。 実際にはすべてがかなり間違っているからです。



私が犯した多くの間違いは、これが私が思うように働くと確信したという事実によるものでした。 私はこれを信じており、そうでなければ可能性を許しませんでした。 もちろん、キャプテンエビデンスはあなたが信じる必要はないと言うでしょう-あなたはドキュメントを読む必要があります。 そして、読んで、読んで、覚えて、覚えてください。 すべてのささいなことをメモリに保持することは可能ですか? そして、フレームワークではなく開発者に転送するのは正しいですか?



さて、根拠がないように-例に移りましょう。 私たちを待っています:

  1. 削除できない取り外し不可能なモデル
  2. 検証されていない有効なフィールド
  3. データを台無しにする2人の管理者




1.管理パネルでオブジェクトを削除する



deleteメソッドをオーバーライドしたいモデルがあると想像してください。 最も単純な例は、 name == 'Root'



モデルを削除したくないということです。 最初に思い浮かぶのは、目的のモデルのdelete()メソッドを単にオーバーライドすることです。



 class SomeModel(models.Model): name = models.CharField('name', max_length=100) def delete(self, *args, **kwargs): if self.name == 'Root': print('No, man, i am not deletable! Give up!') #   "Root"    else: super(SomeModel, self).delete(*args, **kwargs) #    -   delete()
      
      





チェックしてみて?







うまくいく! 次に、同じことを行いますが、モデルのリストのページから:







Delete()は呼び出されず、モデルは削除されます。

これはドキュメントに記載されていますか? はい

なぜこれが行われるのですか? 効率のため。

この効率は、得られた暗黙の動作に値しますか? ほとんどない。

どうする たとえば、(モデルリストページから)一括削除を完全に無効にします。

 class SomeModelAdmin(admin.ModelAdmin): model = SomeModel def get_actions(self, request): actions = super(self.__class__, self).get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions
      
      







これらは私が最初に踏み込んだジャンゴレーキでした。 そして、すべての新しいプロジェクトでは、この振る舞いを念頭に置いて、忘れないでください。



2.バリデーター



バリデーターは、値が何らかの基準に適合しない場合、ValidationErrorをスローして値を受け取る関数です。 バリデーターは、さまざまな種類のフィールドで何らかの検証を再利用する必要がある場合に役立ちます。


たとえば、正規表現に対してフィールドをチェックする場合: RegexValidator

name



フィールドには文字のみを許可します。

 class SomeModel(models.Model): name = models.CharField('name', max_length=100, validators=[RegexValidator(regex=r'^[a-zA-Z]+$')])
      
      









管理パネルでは、検証が機能します。 そして、このような場合:

 # views.py def main(request): new_model = SomeModel.objects.create(name='Whatever you want: 1, 2, 3, etc. Either #&*@^%!)(_') return render( request, 'app/main.html', { 'new_model': new_model, } )
      
      





create()を使用すると、任意の名前を指定でき、 検証は呼び出されません



これはドキュメントに記載されていますか? はい

モデルの保存時にバリデーターが自動的に呼び出されることはありませんが、ModelFormを使用すると、バリデーターはフォームに含まれるフィールドに対して機能することに注意してください。


これは明らかですか? フォーム内のフィールドを検証する必要があるが、他の場合は検証しない状況を想像してみました。 そして、私にはアイデアがありません。 フィールドの検証をグローバルに行うのがより論理的です。つまり、文字だけを指定すると、敵はすべて通過せず、パサランは通過しないことが指定されている場合、これを回避することはできません。 この制限を削除する場合は、model.save()を再定義し、必要に応じて検証を無効にします。

どうする 保存する前に検証を明示的に呼び出します。

 @receiver(pre_save, sender=SomeModel) def validate_some_model(instance, **kwargs): instance.full_clean()
      
      







3. 2人の管理者



MishaとPetyaがサイトを管理しています。 1000番目のレコードの後、ミーシャはレコード#1001(「人生の意味」)の編集フォームを開いたままにして、お茶を飲みに行きました。 この時点で、Petyaは同じレコード#1001を開き、名前を変更しました(「意味がありません」)。 ミーシャが戻り(「古い」レコード「人生の意味」はまだ開いています)、「保存」をクリックしました。 プチの文章は詰まっていた。



これは、「 楽観的ロック/楽観的同時実行制御 」の欠如と呼ばれます。



そのような衝突のために、同時に働く2人の管理者が必要であり、サイトを単独で、したがって家で維持する必要があると思う場合、私はあなたを怒らせます:管理者が1人だけでも機能します。 たとえば、管理者が製品を編集し、その時点でユーザーがquantity



フィールドの値を減らして製品を購入しました。 管理者では、 quantity



フィールドに古い値が含まれているため、[保存]をクリックするとすぐに...



ジャンゴは何と関係がありますか? また、 djangoは管理パネルを提供しますが、楽観的なロックは提供しません 。 そして、管理パネルでの作業を開始するとき、データの奇妙な「上書き」と量の不一致が始まるまで、この問題について考えることすらありません。 それでは、魅力的なデバッグです。



これはドキュメントに記載されていますか? いや

どうする



簡単に説明すると、モデルごとにversion



フィールドを作成し、保存時にバージョンが変更されていないことを確認し、値を1増やします。変更された場合は、例外をスローします(他の誰かが既にレコードを変更したことを意味します)。



道徳



結論として、私が始めたものを繰り返します。

Djangoはあなたが思うようには動作しません。 Djangoは、ドキュメントに書かれているとおりに機能します。 多かれ少なかれ。



それに関するドキュメントのセクション全体を読むまで、既存の機能を確認することはできません。 ドキュメントで明示的に記述されていない場合、機能の可用性に依存することはできません。 これらは明らかな真実です...あなたが出くわすまで正確に。



All Articles