使用 Django
5.0.2
,让我们从一个简单的模型开始:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
我想在
ModelForm
内进行一些表单验证,以确定是否应在DeleteView
内进行删除。简而言之,我认为该表单已经能够显示非字段错误,并且我想避免使用 messages.error()
发回错误消息。
所以我从
ModelForm
开始:
from django.forms import ModelForm
class DeleteBookForm(ModelForm):
class Meta:
model = Book
fields = []
def clean(self):
super().clean()
if not self.deletable():
self.add_error(None, 'This object can not be deleted')
def deletable(self) -> bool:
# do some evaluation on Book here
book = self.instance
if book.title == 'delete me please':
return True
else:
return False
然后是
DeleteView
:
from django.views.generic import DeleteView
from django.http import HttpResponseRedirect
class DeleteBookView(DeleteView):
model = Book
form_class = DeleteBookForm
def form_valid(self, form):
self.object.delete()
messages.success(self.request, 'The object has been deleted successfully.')
return HttpResponseRedirect(self.get_success_url())
但是
self.instance
似乎是None
在DeleteBookForm.deletable()
里面。指示 Book
模型实例在创建时未提供/插入到 ModelForm
。我相信UpdateView
情况并非如此。
花了一些时间阅读,我在
BaseDeleteView.post()
(DeleteView
的父级)上找到了这段代码。请注意,它确实没有将对象插入到表单中:
class BaseDeleteView(DeletionMixin, FormMixin, BaseDetailView):
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
最终,我所做的就是在创建表单时手动插入实例:
class DeleteBookView(DeleteView):
def get_form(self, form_class=None):
# insert instance so it can be read inside the form
return self.form_class(
instance=self.object,
**self.get_form_kwargs()
)
再次强调,模型实例是在
UpdateView
中默认提供的。
所以我的问题是:
DeleteView
默认不提供模型实例?ModelForm
上使用DeleteView
进行模型实例评估是错误的吗?我不确定,但我觉得 Form 是放置模型实例评估的最合乎逻辑的方式,而不是在 View 上。您只需要混合
ModelFormMixin
,即可将对象传递到表单:
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import ModelFormMixin
class DeleteBookView(SuccessMessageMixin, ModelFormMixin, DeleteView):
model = Book
form_class = DeleteBookForm
success_message = 'The object has been deleted successfully.'