Django中通过或不通过表单对象提交外键字段到模型的实现方案
Django 非ModelForm方式保存模型外键实现方案
你不需要依赖ModelForm完成外键数据的写入,Django原生支持直接给模型外键字段赋值保存,以下是可直接落地的实现方式:
方式一:赋值外键对应模型实例
只要拿到关联的外键模型实例,直接赋值给外键字段后调用save()即可,完全不需要经过表单逻辑:
# 从请求参数中获取用户选中的作者ID selected_author_id = request.POST.get("selected_author") # 查询到对应的作者模型实例 matched_author = Author.objects.get(id=selected_author_id) # 新建书籍场景 new_book = Books( title = request.POST.get("book_name"), publish_time = request.POST.get("publish_date"), # 其他书籍字段按正常逻辑赋值 author = matched_author ) new_book.save() # 更新已有书籍场景 book = Books.objects.get(id=request.POST.get("book_id")) book.author = matched_author book.save()
方式二:直接赋值外键ID(性能更优)
Django会为每一个外键字段自动生成后缀为_id的属性,你可以直接把外键关联对象的主键值赋值给这个属性,省去提前查询外键实例的步骤:
selected_author_id = request.POST.get("selected_author") # 新建书籍 new_book = Books( title = request.POST.get("book_name"), author_id = selected_author_id ) new_book.save() # 更新书籍 book = Books.objects.get(id=request.POST.get("book_id")) book.author_id = selected_author_id book.save()
注意:使用该方式需要提前校验传入的作者ID是否真实存在于作者表中,否则保存时会触发数据库外键约束报错。
搜索选择作者场景的落地逻辑
你描述的用户搜索选作者的场景完全可以用上述方式实现,不需要依赖ModelForm渲染的外键选择框:
- 前端单独实现作者搜索接口,根据用户输入的关键词返回匹配的作者列表,每个选项绑定对应作者ID
- 用户选中作者提交表单时,将选中的作者ID和其他书籍字段一同提交到后端
- 后端拿到参数校验后,用上面两种方式任意一种给Book模型的外键字段赋值,完成保存即可。
如果你还是希望保留ModelForm的校验能力,但不想用它自动生成的外键选择控件,可以手动覆写字段:
class BooksForm(forms.ModelForm): # 覆写外键字段,直接接收前端传的作者ID author = forms.IntegerField() class Meta: model = Books fields = "__all__" def clean_author(self): author_id = self.cleaned_data["author"] try: return Author.objects.get(id=author_id) except Author.DoesNotExist: raise forms.ValidationError("所选作者不存在")
这种写法下你可以完全自定义前端的搜索交互逻辑,只要提交时把选中的作者ID传给author参数,表单校验通过后会自动完成外键关系的存储。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

