2009-04-17 59 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,所以這應該是可靠的。

相關問題