【问题标题】:Django, save ModelFormDjango,保存模型窗体
【发布时间】:2014-05-09 12:01:23
【问题描述】:

我创建了一个模型 Student,它从 Django 用户 扩展而来,是另一个模型的外键,同时它有一个名为 year 的整数字段。我想要做的是保存一个表单,它有 2 个字段。一个是课程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']

【问题讨论】:

  • 你能不能试着写3行代码而不是form.save()obj = form.save(commit=False)obj.course_id = request.POST['course'],然后obj.save()
  • 试过了,但仍然出现此错误无法分配“u'1'”:“Student.course”必须是“Course”实例。
  • 你在哪里分配用户的课程?因为我没有得到您分配课程属性的代码。
  • 如果这就是您的意思,那么学生模型对课程模型有一个“课程”外键。

标签: python django django-forms


【解决方案1】:

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

【讨论】:

  • 这对我不起作用。为尚无模型实例的用户提交此表单时,我收到 NOT NULL constraint failed: appname_modelname.user_id 错误。
  • @Bibhas 你能帮忙解决类似的问题吗stackoverflow.com/questions/55384218/…
  • @Pieter,你必须使用 commit = False,然后你可以将用户附加到你的模型,然后你 .save() 发送到数据库。如果你有关系,不要尝试 form.save(commit=True)。
【解决方案2】:

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

您需要验证课程 ID 是否有效,因此将该代码放入 clean 方法中并不是一个坏主意。还要注意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 的实例

【讨论】:

  • 不幸的是,我收到一条错误消息,提示 int() 参数必须是字符串或数字,而不是“课程”
  • 对不起,这是我的错。我将字段名称从“course”更改为“course_id”以防止类型冲突,并忘记更新干净的方法名称。
  • 哦,好的!现在它不会返回错误,但它仍然不会更新数据库。所以在管理面板中,两个字段(课程和年份)都是空的。
  • 让我添加一些额外的代码以确保在模型上正确设置值。
  • 查看我的修改,了解如何将用户传递给表单。
猜你喜欢
  • 2011-04-15
  • 2017-04-07
  • 2018-10-07
  • 2019-10-06
  • 2019-08-22
  • 2016-01-04
  • 2023-03-23
  • 2017-06-16
  • 2018-08-07
相关资源
最近更新 更多