NOT NULL约束失败:表单保存中的owner_id

时间:2016-08-05 11:04:40

标签: python django web-applications

我正在尝试制作一个允许用户上传文件(纯文本字典文件)的表单。这是我的模特:

from django.conf import settings
from django.db import models
import uuid


class Dictionary(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    file = models.FileField(upload_to='uploads/%y/%m/%d')
    timestamp = models.DateTimeField(auto_now_add=True)

这是我用它的表格。我想只公开要设置的用户的文件参数。我打算从请求用户设置的所有者:

from django.forms import ModelForm

from dic.models import Dictionary


class DictionaryForm(ModelForm):

    class Meta:
        model = Dictionary
        fields = ['file']

    def __init__(self, owner, *args, **kwargs):
        self.owner = owner
        super().__init__(*args, **kwargs)

这是我的视图代码,它将发布数据,文件和用户发送到表单:

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render

from dic.forms import DictionaryForm

@login_required
def upload(request):
    if request.method == 'POST':
        form = DictionaryForm(request.user, request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/dic/upload_success')
    else:
        form = DictionaryForm(request.user)
    return render(request, 'dic/upload.html', {'form': form})

这是我失败的测试代码:

def test_can_upload_file(self):
    user = User.objects.create(username='foo')
    user.save()
    self.client.force_login(user)
    self.assertEqual(Dictionary.objects.count(), 0)

    file = StringIO(initial_value='fake data here')
    response = self.client.post('/dic/upload', {'file':file})
    self.assertEqual(response.status_code, 200)

断言行永远不会运行,因为首先发生错误。生成的错误位于form.save()的视图代码中。生成的错误是:

django.db.utils.IntegrityError: NOT NULL constraint failed: dic_dictionary.owner_id

两个问题。如何在表单中正确设置所有者值,以便不会发生此错误?为什么错误发生在form.save()行,因为is_valid()应该检查不会发生错误?

1 个答案:

答案 0 :(得分:3)

is_valid()仅验证您在表单中指定的字段(在本例中为file)。表单有效 - 但稍后会出现错误,因为保存时不满足其他模型字段约束。

owner传递给表单不起作用,因为表单不处理该字段。相反,您需要在表单验证后将owner添加到模型中,但在保存之前:

if request.method == 'POST':
    form = DictionaryForm(request.POST, request.FILES)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.owner = request.user
        obj.save()
        return HttpResponseRedirect('/dic/upload_success')

(同时删除表单上的__init__方法)。