Django,保存ModelForm

时间:2014-03-30 02:51:33

标签: python django django-forms

我创建了一个模型学生,它扩展自 Django用户,是另一个模型的外键,同时它有一个名为year的整数字段。我想要做的是保存一个有两个字段的表单。一个是课程ID ,另一个是整数字段。当我点击提交时,我收到错误无法分配“u'2”:“Student.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 个答案:

答案 0 :(得分:38)

如果您已在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',)

答案 1 :(得分:4)

course必须是课程模型的实例,而不仅仅是实例的主键。您仍然可以接受表单中的ID作为文本输入,但您需要检索实际的课程实例并分配值。

您需要验证课程ID是否有效,因此将该代码放入干净的方法并不是一个坏主意。另请注意course字段如何排除在此处?否则表格将会出现。您也不需要重新定义年份字段,因为ModelForm将从Student模型继承该字段。

# 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

的实例