【Django】関数で動的に保存先・保存名を指定する【FileField、ImageField】

※本サイトにはプロモーション・広告が含まれています。

(最終更新月:2021年11月)

✓こんな方へ向けての記事となります

「FileField、ImageFieldで自動でタイトル名を生成し保存したい!」

「動的にファイル名を作成し保存したい!」

✓当記事を通じて伝えること

  • 保存先・ファイル名を関数で動的に指定する方法

通常、FileFiledで保存先を指定する場合は下記の通りです。

FileField(upload_to=”保存先のファイルパス”)

具体的な保存場所としては、settings.pyのMEDIA_ROOTで指定するフォルダ直下となります。

また、保存されるファイル名アップロードするファイル名をそのまま引き継ぐ形となります。

当記事では、下記のステップで関数を使って保存していきます。

  • モデルインスタンスに保存されたCharFieldを受け取る
  • CharFieldの値を保存名とする

順を追って見てきましょう。

※当記事ではFileFieldで説明をしていますが、ImageFieldの場合も同様のやり方になります。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

【副業】ブログ(月間17万PV)/YouTube/Web・アプリ制作

「プログラミング × ライティング × 営業」の経験を活かし、30後半からのIT系職へシフト。当サイトでは、実際に手を動かせるWebアプリの開発を通じて、プログラミングはもちろん、IT職に必要な情報を提供していきます。

【当ブログで紹介しているサイト】

当サイトチュートリアルで作成したデモ版日報アプリ

Django × Reactで開発したツール系Webアプリ

✔人に見せても恥ずかしくないコードを書こう

「リーダブルコード」は、わかりやすく良いコードの定義を教えてくれる本です。

  • 見るからにきれいなコードの書き方
  • コードの分割方法
  • 変数や関数の命名規則

エンジニアのスタンダートとすべき基準を一から解説しています。

何回も読むのに値する本なので、ぜひ手にとって読んでみてください。

はじめに

既にファイルを扱っていて、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では、

  1. CharField「title」に保存された値をファイル名とし、
  2. 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つフォルダを作成する必要があります

  1. MEDIA_ROOTの通り、「media_local
  2. savePath関数の通り、「media_local」内に「files」を作成

【フォルダツリー】

media_local
    └── files #ここにファイルが保存されていきます

まとめ

流れをまとめます

  1. settings.pyでMEDIA_ROOTを設定する
  2. フィールドの引数で「upload_to=関数名」とする
  3. 関数では、ファイルパス を返す
  4. MEDIA_ROOT、関数で指定した通りにフォルダを作成する

関数が増えてきた場合などは、別ファイルにまとめてインポートする方法を使っても良いと思います

以上、ファイルの保存先を関数で動的に指定する方法、でした!

タイトルとURLをコピーしました