Django ModelForm中将外键设为隐藏字段

4 投票
2 回答
2586 浏览
提问于 2025-04-15 16:30

我正在制作一个非常简单的表单。我们就用Django教程里的书籍和出版社的例子来讲解。

用户登录到这个网页应用后,第一件事就是可以点击一个出版社。这个出版社的信息会被保存到他们的会话中。接着,我会把他们带到一个创建书籍的表单。在这个表单里,我会把数据库中出版社的ID放到一个隐藏的字段里。

当用户提交这个表单时,我会做一些操作,比如:

mybookform = BookForm(request.POST)
if mybookform.is_valid():
    abook = mybookform.save(commit=False)
    abook.publisher_id = request.POST['publisher_id']
    mybookform.save()

是的,这里有一些比较简单粗暴的做法,比如直接拿出版社的ID并检查它是否真的是一个有效的出版社ID,还有其他一些安全问题。我们暂时不去关注这些。

我想问的是,有没有更好的处理方式?虽然这个例子在逻辑上可能不太合理,但在我的应用中,这个例子其实是有意义的。问题是我遇到了一个ValueError异常,提示说publisher_id需要是一个出版社实例。

现在我可以很容易地通过Publisher.objects.filter(id=..)来获取一个出版社实例,然后用这个实例。我的问题是,这真的有必要吗?我能不能避免额外查询数据库,而以一种更“优雅”的方式更新这个表单实例呢?

另外,有没有办法把出版社的信息嵌入到一个隐藏字段中,这样我就不需要用mybookform.save(commit=False)来保存,而是直接用mybookform = BookForm(request.POST)然后立即调用mybookform.save()?

2 个回答

1

没有更好的方法来做到这一点。

我会使用 get_object_or_404 这个函数来处理。

而且,是的,你可以通过把模型字段设置为 editable=False 来防止用户修改这个字段。

1

获取发布者的实例可以防止客户端做出一些可能会引用完全无效的发布者的更改。

关于你的第二个问题,是的,你可以通过在ModelForm中重写字段,将那个字段设置为隐藏字段,具体做法是把widget设置为HiddenInput

撰写回答