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



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

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

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

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__方法)。

最新更新