2009-04-17 53 views
10

我可以很容易地用文件名填充Django fixture中FileField或ImageField的字段,但该文件不存在,当我尝试测试我的应用程序时,它失败,因为该文件不存在。你如何在Django的夹具中放置一个文件?

如何正确填充Django夹具中的FileField或Imagefield以便文件本身也可用?

回答

7

恐怕很简单的答案是,你不能使用FileField或ImageField类来做到这一点;他们只是存储一个文件路径,并没有真正的文件实际数据的概念。但是,长时间的回答是,如果您利用Django API编写自己的custom model fields,任何事情都是可能的。

至少,您需要实现value_to_string方法来转换序列化数据(在上面的链接中的django文档中有一个示例)。请注意,上面的URL链接中的示例还包括提及FileField和ImageField的子类,这对您的情况很有帮助!

您还需要决定是将数据存储在数据库还是文件系统中。如果是前者,则必须将您的自定义类实现为Blob字段,包括为您希望支持的每个数据库定制;当HTML请求.gif/.jpg/.png/.whatever url时,您还必须提供一些支持,以便数据如何从数据库中返回给用户。如果后者,这是更好的方式,恕我直言,你必须实现序列化,反序列化二进制数据到文件系统的方法。无论哪种方式,如果您将这些作为FileField和ImageField的子类实现,您仍然应该可以使用Admin工具和其他需要这种django功能的模块。

当且仅当您选择使用更多涉及的blob方法时,以下是处理blob for MySQL和PostgreSQL的老项目代码片段(当我学习Django时)。你可能会找到一些改进,因为我没有触及它:-)但它不处理序列化,所以你必须使用上面的方法添加它。

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

class BlobValueWrapper(object): 
    """Wrap the blob value so that we can override the unicode method. 
    After the query succeeds, Django attempts to record the last query 
    executed, and at that point it attempts to force the query string 
    to unicode. This does not work for binary data and generates an 
    uncaught exception. 
    """ 
    def __init__(self, val): 
     self.val = val 

    def __str__(self): 
     return 'blobdata' 

    def __unicode__(self): 
     return u'blobdata' 


class BlobField(models.Field): 
    """A field for persisting binary data in databases that we support.""" 
    __metaclass__ = models.SubfieldBase 

    def db_type(self): 
     if settings.DATABASE_ENGINE == 'mysql': 
      return 'LONGBLOB' 
     elif settings.DATABASE_ENGINE == 'postgresql_psycopg2': 
      return 'bytea' 
     else: 
      raise NotImplementedError 

    def to_python(self, value): 
     if settings.DATABASE_ENGINE == 'postgresql_psycopg2': 
      if value is None: 
       return value 
      return str(value) 
     else: 
      return value 

    def get_db_prep_save(self, value): 
     if value is None: 
      return None 
     if settings.DATABASE_ENGINE =='postgresql_psycopg2': 
      return psycopg2.Binary(value) 
     else: 
      return BlobValueWrapper(value) 
+0

您的意思是说,要测试使用FielField的应用程序,我应该创建另一个字段类型并将其替换? – Pablo 2009-04-20 05:40:39

+0

不......我把你的问题看作是你想让灯具包含数据的意思。如果您只是测试FileField和ImageField的工作,那么只需测试它们是否生成正确的URL和路径即可......不必担心实际的图像数据。 – 2009-04-20 13:51:56

6

没有办法在序列化夹具中“包含”文件。如果创建一个测试夹具,你只需要自己做;确保一些测试文件实际存在于由FileField/ImageField值引用的位置。这些字段的值是相对于MEDIA_ROOT的路径:如果需要,可以在自定义test_settings.py中的testUpup()方法中设置MEDIA_ROOT ,以确保在放置它们的任何位置都能找到测试文件。

编辑:如果你想这样做在你的设置()方法,你也可以直接default_storage猴补丁:

from django.core.files.storage import default_storage 

class MyTest(TestCase): 

    def setUp(self): 
    self._old_default_storage_location = default_storage.location 
    default_storage.location = '/some/other/place' 

    def tearDown(self): 
    default_storage.location = self._old_default_storage_location 

,似乎工作。 default_storage是a documented public API,所以这应该是可靠的。

相关问题