Django,保存ModelForm
我创建了一个叫Student的模型,它是从Django User扩展而来的,并且它还关联了另一个模型,里面有一个叫做year的整数字段。我现在想做的是保存一个表单,这个表单有两个字段,一个是课程ID,另一个就是那个整数字段year。但是当我点击提交的时候,出现了一个错误:无法分配 "u'2'": "Student.course" 必须是一个 "Course" 实例。
这是我的模型文件 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 个回答
8
course
必须是一个课程模型的实例,而不仅仅是这个实例的主键。你可以在表单中接受一个文本输入的 id,但你需要去获取实际的课程实例并把这个值赋给它。
你需要确认课程的 id 是有效的,所以把这段代码放在清理方法里是个不错的主意。还有注意到这里的 course
字段被排除了吧?否则表单会期待这个字段的存在。你也不需要重新定义年份字段,因为 ModelForm 会从学生模型中继承这个字段。
# forms.py
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 clean_course_id(self):
course_id = self.cleaned_data.get('course_id')
try:
self.course = Course.objects.get(pk=course_id)
except Course.DoesNotExist:
raise forms.ValidationError('Sorry, that course id is not valid.')
return course_id
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.course = self.course
instance.user = self.user
if commit:
instance.save()
return instance
# views.py
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',)
现在,当你在模型上调用 .save()
时,课程字段会被赋值为一个 Course
的实例。
63
如果你已经在fields
属性里提到过字段,就不需要在ModelForm
里重新定义这些字段。所以你的表单应该是这样的 -
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',)