ユーザーが支払いの注文を送信するDjangoアプリがあります。明らかに、セキュリティは重要です。作成するコードの量を最小限に抑え、セキュリティ ホールの発生を回避し、メンテナンスを容易にしたいと考えています。
モデルは単純です。
class Order(models.Model):
user = models.ForeignKey(User)
created = models.DateTimeField()
paid = models.DateTimeField(null=True, blank=True)
items = models.ManyToManyField(Item)
CreateViewを使用してOrder のインスタンスを作成しています。
class OrderView(CreateView):
model = Order
form_class = OrderForm
これらのインスタンスの特定のフィールドに値を適用したいと考えています。たとえば、インスタンスuser
フィールドを現在ログインしているユーザーに設定します。ユーザーがこのフィールドの値を変更できる可能性を望んでいないので、フォームにまったく表示したくありません。したがって、カスタムModelFormを使用して、これらのフィールドをフォームから削除します。
class OrderForm(forms.ModelForm):
class Meta:
model = Order
# For security, we control exactly which fields are placed
# in the form, rather than excluding some:
fields = ('items',)
次に、新しく作成された Order インスタンスのuser
フィールドを現在ログインしているユーザーに設定します。これを行う最善の方法についてのドキュメントが見つかりません。
(A)保存する前にフォームのメソッドをオーバーライドしsave()
てオブジェクトを変更することはできますが、このコードは、フィールドについて何も知らないフォームに属していないように感じuser
ます。request
また、現在のユーザーを特定するために必要な hereへのアクセス権もありません。しかし、次のようになります。
class OrderForm(forms.ModelForm):
def save(self, commit=True):
instance = super(OrderForm, self).save(commit=False)
instance.user = get_request_magic().user
if commit:
instance.save()
return instance
(B)ビューのform_valid
メソッドをオーバーライドして、この質問のクラスベース バージョンのように、commit=False でオブジェクトを保存できます。しかし、スーパークラス メソッドを直接呼び出すことはできません。コミットを無効にする方法がないため、オブジェクトを保存するため、form_valid
厄介な世代を手動でスキップする必要があります。その苦情は別として、これは私がこれまでに見つけた最良の方法のように見えます:
class OrderView(CreateView):
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super(ModelFormMixin, self).form_valid(form)
(C)CreateView
オブジェクトを保存する前に変更できるようにするためのフックを追加するの代替を書くことができます。しかし、それはより多くのボイラープレートと重複のように感じます.
(D)値を入力するフォーム フィールドがないため、initial
値を指定できません。無視されます。
他のアイデアはありますか?(B) が最良の選択肢である場合、どのスーパークラスのform_valid
メソッドを呼び出したいかを手動で指定するハックな方法を回避する方法はありますか?