(最終更新月:2021年11月)
✓こんな方へ向けての記事となります
「FileField、ImageFieldで自動でタイトル名を生成し保存したい!」
「動的にファイル名を作成し保存したい!」
✓当記事を通じて伝えること
- 保存先・ファイル名を関数で動的に指定する方法
通常、FileFiledで保存先を指定する場合は下記の通りです。
FileField(upload_to=”保存先のファイルパス”)
具体的な保存場所としては、settings.pyのMEDIA_ROOTで指定するフォルダ直下となります。
また、保存されるファイル名はアップロードするファイル名をそのまま引き継ぐ形となります。
当記事では、下記のステップで関数を使って保存していきます。
- モデルインスタンスに保存されたCharFieldを受け取る
- CharFieldの値を保存名とする
順を追って見てきましょう。
※当記事ではFileFieldで説明をしていますが、ImageFieldの場合も同様のやり方になります。
はじめに
既にファイルを扱っていて、MEDIA_ROOTの設定ができている方は次章へお進みください
「まだ設定が終わってない!」という方は、settings.py内に下記を追記します
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media_local'
MEDIAファイルの保存先は「media_local」というフォルダ名にしました
お好きなフォルダ名にして頂いて構いません
今回使用するモデルクラス
今回使用するモデルクラスは、簡易的なものとし、フィールド「タイトル」と「ファイル」の2つで構成されています。
class FileSavingClass(models.Model):
title = models.CharField(max_length=100)
file = models.FileField(upload_to=savePath)
def __str__(self):
return self.title
FileFieldの引数で「upload_to=」にsavePathを代入しています
次章で「savePath」関数を作っていきます
「savePath」関数の作成と解説
savePathでは、
- CharField「title」に保存された値をファイル名とし、
- MEDIA_ROOTで指定したフォルダ直下の「files」というフォルダに保存する
ための文字列を返しています
def savePath(instance, filename):
ext = filename.split('.')[-1]
new_name = instance.title + "_saved"
return f'files/{new_name}.{ext}'
一つ一つ解説します
【1行目】
def savePath(instance, filename):
引数として、「instance」と「filename」を受け取ります
- 「instance」は保存されるモデルクラスのオブジェクトそのもの
- 「filename」はアップロードされるファイル名
が代入されます
【2行目】
ext = filename.split('.')[-1]
「filename」には拡張子も含めたファイル名が格納されています
splitメソッドで、拡張子だけ取り出しています
【3行目】
new_name = instance.title + "_saved"
「instance」にはモデルクラスオブジェクトが格納されているので、
instance.title + “_saved”
で、タイトルフィールドに入力した値_savedというファイル名で保存されるよう文字列を作っています
【4行目】
return f'files/{new_name}.{ext}'
ファイル名を含めたファイルパス を返します
MEDIA_ROOTで指定したフォルダ以下のパスを文字列で記述します
この場合だと、「files」フォルダ内に保存するよう指示しています
フォルダの作成する
今回は2つフォルダを作成する必要があります
- MEDIA_ROOTの通り、「media_local」
- savePath関数の通り、「media_local」内に「files」を作成
【フォルダツリー】
media_local └── files #ここにファイルが保存されていきます
まとめ
流れをまとめます
- settings.pyでMEDIA_ROOTを設定する
- フィールドの引数で「upload_to=関数名」とする
- 関数では、ファイルパス を返す
- MEDIA_ROOT、関数で指定した通りにフォルダを作成する
関数が増えてきた場合などは、別ファイルにまとめてインポートする方法を使っても良いと思います
以上、ファイルの保存先を関数で動的に指定する方法、でした!