如何在Django中将表单输入关联到模型?
在Django中,我怎么把一个表单和一个模型关联起来,这样在表单中输入的数据就能插入到和模型相关的数据库表里呢?我该怎么把用户输入的数据保存到那个数据库表中呢?
举个例子:
class PhoneNumber(models.Model):
FirstName = models.CharField(max_length=30)
LastName = models.CharField(max_length=30)
PhoneNumber = models.CharField(max_length=20)
class PhoneNumber(forms.Form):
FirstName = forms.CharField(max_length=30)
LastName = forms.CharField(max_length=30)
PhoneNumber = forms.CharField(max_length=20)
我知道有一个类可以用来从模型创建表单,但即使这样,我也不太明白数据是怎么实际存到数据库里的。我想先搞清楚这个过程再去了解一些省时的技巧。如果文档中有简单的例子说明这个是怎么工作的,我可能错过了。
谢谢。
更新:
为了更清楚,我知道有ModelForm这个工具,我想弄明白怎么在不使用它的情况下实现这个功能,部分原因是我想更好地理解它到底在做什么。
回答:
在大家的帮助下,我找到了这个解决方案:
表单定义:
class ThisForm(forms.Form)
[various Field assignments]
model = ThisModel()
在视图中保存输入数据到数据库的代码:
if request_method == 'POST':
form = ThisForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.items():
setattr(form.model, key, value)
form.model.save(form.model)
这样一来,在浏览器表单中输入的数据就成功存到了数据库表里。
注意,调用模型的save()方法时需要把模型本身作为参数传入。我也不知道为什么。
注意:我还是个新手。这种方法成功地把数据从浏览器传到了数据库表里,但我不知道在这个过程中我忽略了什么、错过了什么,或者搞坏了什么。ModelForm看起来确实是一个更干净的解决方案。
4 个回答
我觉得ModelForm.save的说明应该讲得更清楚一些。使用它的基础类(Form)时,你需要手动用Form.cleaned_data()来获取字段的值,然后把这些值一个个设置到对应的模型字段里。而ModelForm会为你自动完成这些工作。
我不太确定你指的是哪个类。我知道之前有一个助手,类似于 form_for_model
(具体名字我记不太清了;那是在1.0版本发布之前的事)。现在我这样做:
import myproject.myapp.models as models
class PhoneNumberForm(forms.ModelForm):
class Meta:
model = models.PhoneNumber
要了解背后的元类魔法,你得看看代码,因为有很多东西需要解释 :]. 表单的构造函数可以接受一个 instance
参数。传入这个参数后,表单就会对一个已有的记录进行操作,而不是创建一个新的记录。更多信息可以在 这里找到。
当我第一次使用表单和模型(没有使用ModelForm的时候),我记得我做的事情是先检查表单是否有效,这样就能得到清理过的数据,然后手动把这些数据从表单转移到模型里(或者进行其他处理),最后再保存这个模型。可以想象,这个过程非常繁琐,尤其是当你的表单和模型几乎一模一样的时候。通过使用ModelForm(因为你说你不太确定它是怎么工作的),当你保存ModelForm时,它会根据模型的规范用表单数据创建一个对象,然后帮你保存这个模型。所以,总的来说,数据的流动顺序是:从HTML表单,经过Django表单,再到Django模型,最后到数据库。
这里有一些实际的代码来回答你的问题:
要把浏览器中的表单数据放入表单对象,可以这样做:
if request.method == 'POST':
form = SomeForm(request.POST)
if form.is_valid():
model.attr = form.cleaned_data['attr']
model.attr2 = form.cleaned_data['attr2']
model.save()
else:
form = SomeForm()
return render_to_response('page.html', {'form': form, })
在模板页面中,你可以这样使用表单:
<form method="POST">
{{ form.as_p }}
<input type="submit"/>
</form>
这只是我从这里提取的一个例子。