DjangoフィクスチャのFileFieldまたはImageFieldのフィールドにファイル名を簡単に入力できますが、そのファイルは存在せず、アプリケーションをテストしようとすると、そのファイルが存在しないために失敗します。
ファイル自体も使用できるように、Django フィクスチャで FileField または Imagefield を正しく設定するにはどうすればよいですか?
残念ながら、短い答えは、FileField または ImageField クラスを使用してこれを行うことはできないということです。ファイル パスを格納するだけで、ファイルの実際のデータに関する実際の概念はありません。ただし、Django API を利用して独自のカスタム モデル フィールドを記述すれば、何でも可能です。
少なくとも、value_to_string
シリアル化のためにデータを変換するメソッドを実装する必要があります (上のリンクの django ドキュメントに例があります)。上記の URL リンクの例には、FileField と ImageField のサブクラス化についての言及も含まれていることに注意してください。これは、状況に役立ちます!
したがって、データをデータベースに保存するか、ファイル システムに保存するかを決定する必要もあります。前者の場合、サポートするすべての DB のカスタマイズを含め、カスタム クラスを Blob フィールドとして実装する必要があります。また、HTML が .gif/.jpg/.png/.whatever url を要求したときに、データをデータベースからユーザーに返す方法をサポートする必要があります。後者の場合は、IMHO へのよりスマートな方法であり、バイナリ データをファイル システムにシリアライズ、デシリアライズするためのメソッドを実装する必要があります。いずれにせよ、これらを FileField と ImageField のサブクラスとして実装した場合でも、そのような django 機能を期待する管理ツールやその他のモジュールを使用できるはずです。
より複雑な blob アプローチを使用することを選択した場合にのみ、MySQL と PostgreSQL の blob を処理する古いプロジェクト (私が 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)
シリアル化されたフィクスチャにファイルを「含める」方法はありません。テスト フィクスチャを作成する場合は、自分で行う必要があります。FileField/ImageField 値によって参照される場所にいくつかのテスト ファイルが実際に存在することを確認してください。これらのフィールドの値は、MEDIA_ROOT からの相対パスです。必要に応じて、MEDIA_ROOT を設定できます。テストの setUp() メソッドでカスタムの test_settings.py で、どこに置いてもテスト ファイルが確実に見つかるようにします。
EDIT : setUp() メソッドで実行したい場合は、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 は文書化されたパブリック APIであるため、信頼できるはずです。