在删除一个对象之前进行验证的最佳方法是什么?例如,在我的设置中有两个模型-Game
和Team
(这两个模型显然是相关的)。用户应该只能删除没有绑定到任何游戏的团队。
我创建了一个表单(没有任何字段)用于删除团队...
class TeamDeleteForm(ModelForm):
class Meta:
model = Team
fields = []
def clean(self):
# Check to see if this team is tied to any existing games
if self.instance.gameteams_set.exists():
raise ValidationError("This team is tied to 1 or more games")
return super().clean()
但是后来我意识到基于类的视图DeleteView没有任何形式的form_valid()方法。我应该扩展通用的FormView而不是DeleteView吗?或者我缺少一个更好的方法?
5条答案
按热度按时间e4eetjau1#
我认为最好的方法是重写模型的delete方法。
lstz6jyr2#
对于您的特定情况,我将简单地覆盖视图的
queryset
属性,以排除具有关联的Game
的Team
。有一个Django ticket opened to make the
DeleteView
behave like other form views,但是在the proposed patch被合并和发布之前(它不会出现在1.8中),您必须完全覆盖视图的delete
方法,如下所示:编辑:
从你接受的解决方案来看,你似乎试图在模型级别阻止删除,这样的强制应该通过使用
PROTECT
on_delete
处理程序来完成。您仍然需要处理视图中凸起的
ProtectedError
:您甚至可以使用
e
的protected_objects
属性来显示更有意义的错误消息,就像管理员所做的那样。gxwragnw3#
我在这个场景中使用了DeleteView和FormView,两者都有各自的优点和缺点。
DeleteView很好,因为它是基于SingleObjectMixin的,你可以很容易地访问你想要删除的对象。一个很好的方法是在get_object中引发一个异常。这样你就可以在get和post上都引发异常。
FormView很好,因为你可以利用form_invalid和clean方法,但是你仍然需要做一些工作来获得对象,设置一些表单(在deleteview中不需要)。
这其实是你想如何解决的问题。还有一些问题是:你是否在GET时引发异常,或者你是否想显示一个漂亮的页面,让用户知道他们不能删除对象。这可以在两种视图类型中完成。
更新你的问题,如果你有更多的点去,我会更新我的回应。
rbl8hiat4#
另一种方法是使用django.db IntegrityError!
68de4m5k5#
覆盖模型的delete方法(这里的大多数答案都是这样做的)在Django4.0中不再起作用。
根据
FormMixin
,POST请求的对象删除在form_valid()
中处理。delete()
处理程序中的自定义删除逻辑应根据需要移到form_valid()
或共享帮助器方法中。还有一个讨论here。