Django - forms.Form 无法保存当前用户并且表单有效但未保存

Posted

技术标签:

【中文标题】Django - forms.Form 无法保存当前用户并且表单有效但未保存【英文标题】:Django - forms.Form can't save current user and form is valid but not saved 【发布时间】:2015-12-04 02:20:03 【问题描述】:

我修改了我的代码以使用forms.ModelForm,以便我可以修改网页表单的宽度。我现在遇到的问题是ForeignKeys不适用于forms.Form,我需要在form中保存活动用户,以及提交请求的当前时间。

以下是我使用当前解决方法的文件(我排除了所有必要的导入),它给了我以下错误:table chemrun_chemrun has no column named owner_id。我很高兴有任何帮助来解决这个问题:)

来自models.py

class ChemRun(models.Model):
    owner           =       models.ForeignKey('auth.User')

来自forms.py

class ChemRunForm(forms.ModelForm):
    title           =       forms.CharField(max_length=50)
    status          =       forms.CharField(max_length=20, initial="In queue")
    created_date    =       forms.DateTimeField(initial=timezone.now, required=False)

    def __unicode__(self):
            return self.title

    class Meta:
            model   =       ChemRun
            exclude =       'created_date', 'status', 'owner'

来自views.py

@verified_email_required
def create(request):
    if request.POST:
            form = ChemRunForm(request.POST)
            if form.is_valid():
                    m = form.save(commit=False)
                    m.created_date  =       timezone.now
                    m.owner         =       request.user
                    m.save()
                    return HttpResponseRedirect('/accounts/profile')
    else:
            form = ChemRunForm()

    args = 
    args.update(csrf(request))
    args['form'] = form

    return render_to_response('interface/newrun.html', args, context_instance=RequestContext(request))

来自 urls.py

urlpatterns = [
    url(r'^create/$', 'chemrun.views.create', name='create'),
]

【问题讨论】:

“我修改了我的代码以使用 forms.Form 以便我可以修改表单的宽度” - 根本没有遵循。您可以以完全相同的方式修改 ModelForm 的字段宽度。 我的错,我的意思是写我修改为使用forms.ModelForm 这似乎与表单无关。错误消息说缺少列;这意味着您尚未创建和运行迁移。 好的,我尝试了 makemigrations 调用,并收到以下消息 You are trying to add a non-nullable field 'owner' to chemrun without a default; we can't do that (the database needs something to populate existing rows). 在进行这些更改之前,使用与现在相同的命令将当前用户添加到我的表单中没有问题:owner = models.ForeignKey('auth.User')。特别是,我不需要添加默认值来分配所有者值,但现在出于某种原因我需要。 不,这是不可能的。在运行迁移之前,您将无法将用户添加到对象中,因为您没有外键。该错误消息告诉您需要为 现有 对象提供一次性默认值,而不是任何新对象。 【参考方案1】:

我看到了两个实用的解决方案:

    由于字段“所有者”是模型中的新字段,因此您必须在迁移中添加一个默认 id,以将其放入已存在数据的列中。 您可以在 'owner' 字段中设置 'blank=null',这样 django 就不会强制该列中的数据。

您在 cmets 中说过,在命令 'makemigrations' 之前没有要求您提供任何东西,而现在它确实要求您提供任何东西,这是因为现在您在该表中有记录,如果您添加新列,django 或 postgres 都不知道在旧记录的那一列中放什么,也许你可以“刷新”你的数据库?当然,前提是它是一个开发数据库。

【讨论】:

谢谢,我刚刚对此进行了测试,在删除数据库和所有以前的迁移后,页面运行。现在唯一剩下的问题是表单收集的数据没有保存到数据库中,否则无法访问数据库。 您删除数据库中的数据后是否再次运行makemigrations? 是的,我创建了一个超级用户来访问管理页面,并创建了一个普通用户来运行脚本来创建表单。 manage.py makemigrations 给我No changes detected 你是否在 makemigrations 之后运行了 migrate? 是的,我还运行了 collectstatic 以防万一。什么都没有【参考方案2】:

经过更多的阅读和实验,我发现了一些额外的要点,可以为该问题的未来读者添加。

错误的第一部分是由于无法成功运行命令makemigrations 和随后的migrate 而导致的。由于错误,我从迁移目录中删除了__init__.py。恢复文件并重新运行命令后,该部分已得到纠正。对于未来,我可以推荐以下脚本来清理/重置迁移(取自this question 的答案之一)。

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

第二部分是能够调整字段的宽度。我在 models.py 中定义了我的字段,但是通过在 forms.py 中添加对等价表单类的 Meta 类的小部件调用,我可以调整它等等。这是我的forms.py:

class ChemRunForm(forms.ModelForm):
    class Meta:
        model = ChemRun
        widgets =       'title': forms.TextInput(attrs='style':'width: 500px;')
        exclude = ('owner')

注意:ChemRun 是模型类,ChemRunForm 是表单类。 titleowner 是我模型的两个字段。

希望这对未来的人们有所帮助

【讨论】:

以上是关于Django - forms.Form 无法保存当前用户并且表单有效但未保存的主要内容,如果未能解决你的问题,请参考以下文章

Django绑定表单无效,但未引发ValidationError

重修课程day60(django之form组件)

django的Form表单

django Form表单模块实例

django中的Form

Django的form组件