3
我有一個Attachment
模型,在Django 1.4.1應用程序中有FileField
。這FileField
有一個可調用的upload_to
參數,其中每Django docs應該保存表格(並因此保存模型)時調用。Django FileField沒有保存到upload_to位置
當我運行下面FormTest
,則upload_to
調用,不會被調用該文件,因此不會出現在由upload_to
方法提供的位置。我究竟做錯了什麼?
請注意,在ModelTest
(也在下文)的合格測試中,upload_to
方法按預期工作。我已經看過那些
事情不似乎是這個問題:
- 在
Attachment
模型的屬性的順序。我發現了一些似乎表明這個順序很重要的問題。由於我的upload_to
方法使用directory
屬性,我以爲他可能會導致問題。它不是。這不會導致方法不被調用。 - 或許
is_valid()
未被調用。不,我已經證實它是。 - ...
測試:
from core.forms.attachments import AttachmentForm
from django.test import TestCase
import unittest
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files.storage import default_storage
def suite():
return unittest.TestSuite(
[
unittest.TestLoader().loadTestsFromTestCase(FormTest),
]
)
class FormTest(TestCase):
def test_form_1(self):
filename = 'filename'
f = file(filename)
data = {'name':'name',}
file_data = {'attachment_file':SimpleUploadedFile(f.name,f.read()),}
form = AttachmentForm(data=data,files=file_data)
self.assertTrue(form.is_valid())
attachment = form.save()
root_directory = 'attachments'
upload_location = root_directory + '/' + attachment.directory + '/' + filename
self.assertTrue(attachment.attachment_file) # Fails
self.assertTrue(default_storage.exists(upload_location)) # Fails
附件型號:
from django.db import models
from parent_mixins import Parent_Mixin
import uuid
from django.db.models.signals import pre_delete,pre_save
from dirtyfields import DirtyFieldsMixin
def upload_to(instance,filename):
return 'attachments/' + instance.directory + '/' + filename
def uuid_directory_name():
return uuid.uuid4().hex
class Attachment(DirtyFieldsMixin,Parent_Mixin,models.Model):
attachment_file = models.FileField(blank=True,null=True,upload_to=upload_to)
directory = models.CharField(blank=False,default=uuid_directory_name,null=False,max_length=32)
name = models.CharField(blank=False,default=None,null=False,max_length=128)
class Meta:
app_label = 'core'
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return unicode(self.name)
@models.permalink
def get_absolute_url(self):
return('core_attachments_update',(),{'pk': self.pk})
# def save(self,*args,**kwargs):
# super(Attachment,self).save(*args,**kwargs)
def pre_delete_callback(sender, instance, *args, **kwargs):
if not isinstance(instance, Attachment): return
if not instance.attachment_file: return
instance.attachment_file.delete(save=False)
def pre_save_callback(sender, instance, *args, **kwargs):
if not isinstance(instance, Attachment): return
if not instance.attachment_file: return
if instance.is_dirty():
dirty_fields = instance.get_dirty_fields()
if 'attachment_file' in dirty_fields:
old_attachment_file = dirty_fields['attachment_file']
old_attachment_file.delete()
pre_delete.connect(pre_delete_callback)
pre_save.connect(pre_save_callback)
附件形式:
from ..models.attachments import Attachment
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Div,Layout,HTML,Field,Fieldset,Button,ButtonHolder,Submit
from django import forms
class AttachmentFormHelper(FormHelper):
form_tag=False
layout = Layout(
Div(
Div(
Field('name',css_class='span4'),
Field('attachment_file',css_class='span4'),
css_class='span4',
),
css_class='row',
),
)
class AttachmentForm(forms.ModelForm):
helper = AttachmentFormHelper()
class Meta:
fields=('attachment_file','name')
model = Attachment
class AttachmentInlineFormHelper(FormHelper):
form_tag=False
form_style='inline'
layout = Layout(
Div(
Div(
Field('name',css_class='span4'),
Field('attachment_file',css_class='span4'),
Field('DELETE',css_class='span4'),
css_class='span4',
),
css_class='row',
),
)
class AttachmentInlineForm(forms.ModelForm):
helper = AttachmentInlineFormHelper()
class Meta:
fields=('attachment_file','name')
model = Attachment
UPDATE
我也做測試的Attachment
模型類與這些單元測試 - 所有通:
from core.models.attachments import Attachment
from core.models.attachments import upload_to
from django.test import TestCase
import unittest
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
def suite():
return unittest.TestSuite(
[
unittest.TestLoader().loadTestsFromTestCase(ModelTest),
]
)
class ModelTest(TestCase):
def test_model_minimum_fields(self):
attachment = Attachment(name='name')
attachment.attachment_file.save('test.txt',ContentFile("hello world"))
attachment.save()
self.assertEqual(str(attachment),'name')
self.assertEqual(unicode(attachment),'name')
self.assertTrue(attachment.directory)
# def test_model_full_fields(self):
# attachment = Attachment()
# attachement.save()
def test_file_operations_basic(self):
root_directory = 'attachments'
filename = 'test.txt'
attachment = Attachment(name='name')
attachment.attachment_file.save(filename,ContentFile('test'))
attachment.save()
upload_location = root_directory + '/' + attachment.directory + '/' + filename
self.assertEqual(upload_to(attachment,filename),upload_location)
self.assertTrue(default_storage.exists(upload_location))
def test_file_operations_delete(self):
root_directory = 'attachments'
filename = 'test.txt'
attachment = Attachment(name='name')
attachment.attachment_file.save(filename,ContentFile('test'))
attachment.save()
upload_location = upload_to(attachment,filename)
attachment.delete()
self.assertFalse(default_storage.exists(upload_location))
def test_file_operations_change(self):
root_directory = 'attachments'
filename_1 = 'test_1.txt'
attachment = Attachment(name='name')
attachment.attachment_file.save(filename_1,ContentFile('test'))
attachment.save()
upload_location_1 = upload_to(attachment,filename_1)
self.assertTrue(default_storage.exists(upload_location_1))
filename_2 = 'test_2.txt'
attachment.attachment_file.save(filename_2,ContentFile('test'))
attachment.save()
upload_location_2 = upload_to(attachment,filename_2)
self.assertTrue(default_storage.exists(upload_location_2))
self.assertFalse(default_storage.exists(upload_location_1))
你可以發佈模板? – jpic
沒有模板或視圖。測試用例直接處理表單。 – Erik
我確實構建了這個測試用例,因爲我使用的視圖/模板沒有將文件上傳到上傳位置。在這裏提供測試用例而不是所有的視圖/模板代碼是我簡化問題的方式 - 視圖/模板代碼中還有很多事情要做。 – Erik