2016-08-05 46 views
0

我試圖製作一個允許用戶上傳文件(純文本字典文件)的表單。這裏是我的型號: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) 

這裏是我的視圖代碼,它發送POST數據,文件和用戶的形式:

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()應該檢查沒有錯誤發生?

回答

2

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

相關問題