【问题标题】:Set user field in a form object created using ModelForm在使用 ModelForm 创建的表单对象中设置用户字段
【发布时间】:2012-02-21 19:25:28
【问题描述】:

我有一个注册表单,当用户在其中输入有效的注册数据时,它会登录用户并将用户重定向到另一个表单以输入更多数据。这个新表单包含更多关于用户的数据,并使用下面的 ModelForm 类创建:

class UserProfileAddForm(ModelForm):
    class Meta:
        model = UserProfile
        exclude = ('user')

UserProfile 模型如下所示:

class UserProfile(models.Model):
    GRADE_YEAR_CHOICES = (
        ('FR', 'Freshman'),
        ('SO', 'Sophomore'),
        ('JR', 'Junior'),
        ('SR', 'Senior'),
        ('GR', 'Graduate')
    )

    school = models.CharField(max_length=64)
    grade_year = models.CharField(max_length=2, choices=GRADE_YEAR_CHOICES)
    gpa = models.DecimalField(decimal_places=2, max_digits=6, blank=True, null=True)
    user = models.ForeignKey(User, unique=True)

其中 user 字段是 Django 的 User 对象的 ForeignKey。我很难将用户字段设置为发出请求的用户。这是我在views.py中尝试过的内容。

第一次尝试:

def more(request):
    if request.method == 'POST':
        form = UserProfileAddForm(request.POST)
        if form.is_valid():
            form.save(commit=False)
            form.user = request.user
            form.save()
            return HttpResponseRedirect('/register/success/')
    else:
        form = UserProfileAddForm()
        variables = RequestContext(request, {
            'form': form

第二次尝试:

def more(request):
    if request.method == 'POST':
        form = UserProfileAddForm(request.POST)
        if form.is_valid():
            form.save(commit=False)
            form.user = User.objects.filter(username=request.user)
            form.save()
            return HttpResponseRedirect('/register/success/')
    else:
        form = UserProfileAddForm()
        variables = RequestContext(request, {
            'form': form
        })
        return render_to_response('registration/more.html', variables)

无论我尝试哪种方式,它似乎都没有将数据保存到数据库中。但是,它会将我重定向到成功页面,就好像它确实成功保存了一样。

【问题讨论】:

    标签: python django forms post


    【解决方案1】:

    form.save() 返回正在保存的模型的实例。您需要在那里设置用户,然后保存该实例。

    profile = form.save(commit=False)
    profile.user = request.user
    profile.save()
    

    请注意,根据request.user 的值从数据库中获取用户是没有意义的,因为request.user 已经是正确的用户对象。

    【讨论】:

    • 效果很好。所以我理解其中的区别,在form 对象中你实际上不能更改实例的值,但在profile 对象中你可以吗?为什么我不能直接做form.user = request.user
    • @NicYoung, Django form objects contain a collection of Field objects,正如您所见,read here 与您要修改的对象完全不同。 form.save() 为您正在保存的对象创建一个新“实例”,您可以修改它。
    • @Dirk 谢谢你的澄清。因此,实际实例化对象使其可修改。这是我必须习惯的。
    【解决方案2】:

    我的建议是您在第二次尝试时进行此更改:

            with_profile = form.save(commit=False)
            with_profile.user = request.user
            form.save()
            ...
    

    问题是您将user 属性添加到form 对象而不是form.instance 对象。

    已编辑

    当我发布第一个答案时,我错误地分配了用户。 @Dirk 已在下面评论它,现在已修复。谢谢@Dirk。问题是查询集被分配给with_profile.user,而不是单个模型。

    【讨论】:

    • 对第一次尝试进行修改会更好,因为它消除了对数据库运行 request.user 中已有的一条数据。另外,第二次尝试不会返回 QuerySet 而不是 User 对象吗?
    • 我想我很难理解form 对象和instance 对象之间的区别。我已经进行了您建议的更改,现在我收到了一个完整性错误:gradebook_userprofile.user_id may not be NULL,因此它似乎没有在实例对象上设置用户字段。
    【解决方案3】:

    好吧,您需要了解的是,当您这样做时,您会得到模型实例 即在你的情况下

    profile = form.save(commit =False)
    

    当您保存模型对象时,它不会保存任何多对多关系。保存模型对象后需要执行的操作。通过这样做,

    form.save_m2m()
    

    所以,只需在保存模型对象后添加最后一段代码即可。

    【讨论】:

      猜你喜欢
      • 2013-01-03
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      相关资源
      最近更新 更多