相对来说,使用ModelForm保存数据在Django中算是比较简单的。主要原因是ModelForm是建立在Django的模型(Model)之上的,它可以自动根据模型的定义生成表单,包括字段和验证规则。这样可以大大简化开发人员处理表单数据的工作。
使用ModelForm保存数据的流程也相对清晰明了:定义模型、创建ModelForm、在视图中处理表单提交。Django的表单系统还提供了很多便捷的功能,比如字段类型的自动转换、数据验证、错误提示等,使得开发者能够更专注于业务逻辑的实现而不是处理表单数据的细节。
虽然说相对简单,但在实际应用中,还是需要开发人员对Django框架有一定的了解和熟悉,尤其是对于复杂的表单和数据处理场景,可能需要更多的定制化工作。
1、问题背景
在 Django 中,我创建了一个扩展自 Django User 的 Student 模型,它是一个外键,指向另一个模型,同时它有一个名为 year 的整数字段。我尝试保存一个包含两个字段的表单,一个字段是课程 ID,另一个字段是整数字段 year。当我点击提交时,我收到一个错误:Cannot assign "u'2'": "Student.course" must be a "Course" instance.
# models.py
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
year = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(7)])
# view.py
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
# forms.py
class SelectCourseYear(forms.ModelForm):
course = forms.CharField()
year = forms.IntegerField(required=True)
class Meta:
model = Student
fields = ['user', 'course', 'year']
2、解决方案
答案 1:
在 ModelForm 中,如果你已经在 fields 属性中提到了字段,那么就不需要重新定义这些字段。所以你的表单应该如下所示:
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
fields = ['course', 'year'] # removing user. we'll handle that in view
然后,我们可以在视图中轻松地处理表单:
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
# commit=False tells Django that "Don't send this to database yet.
# I have more things I want to do with it."
student.user = request.user # Set the user object here
student.save() # Now you can send it to DB
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
答案 2:
course 必须是 Course 模型的实例,而不仅仅是实例的主键。你仍然可以在表单中接受一个 ID 作为文本输入,但是你需要检索实际的 course 实例并分配该值。
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
exclude = ['user', 'course']
course_id = forms.IntegerField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SelectCourseYear, self).__init__(*args, **kwargs)
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.user = self.user
if commit:
instance.save()
return instance
def step3(request):
if request.method == 'POST':
form = SelectCourseYear(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html",
RequestContext(request))
return render(request, 'registration/step3.html',)
这就是使用ModelForm保存数据的基本步骤。当用户提交表单时,视图会验证数据,如果数据有效,则保存到数据库中。
其实上述所讲述的内容也并非过于复杂,只要了解其特性,并且根据自身项目做出调整,这样才能发挥出应有的作用。