web-dev-qa-db-ja.com

djangoを使用して一意のアップロードファイル名を適用しますか?

Djangoを使用して、アップロードされた写真をサーバー上で一意のファイル名に変更する最良の方法は何ですか?それぞれの名前が1回だけ使用されることを確認したいと思います。おそらくGUIDを使用して、これを実行できるpinaxアプリはありますか?

54
zjm1126

Uuidを使用します。これをモデルに関連付けるには、FileField upload_toの Djangoドキュメント を参照してください。

たとえば、models.pyで次の関数を定義します。

import uuid
import os

def get_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    return os.path.join('uploads/logos', filename)

次に、FileField/ImageFieldを定義するときに、get_file_path値としてupload_toを指定します。

file = models.FileField(upload_to=get_file_path,
                        null=True,
                        blank=True,
                        verbose_name=_(u'Contact list'))
127
Nathan

より良い方法は、helpers.pyで共通のクラスを使用することです。この方法で、アプリ全体でランダムファイルジェネレーターを再利用できます。

あなたのhelpers.pyで:

import os
import uuid
from Django.utils.deconstruct import deconstructible


@deconstructible
class RandomFileName(object):
    def __init__(self, path):
        self.path = os.path.join(path, "%s%s")

    def __call__(self, _, filename):
        # @note It's up to the validators to check if it's the correct file type in name or if one even exist.
        extension = os.path.splitext(filename)[1]
        return self.path % (uuid.uuid4(), extension)

次に、モデルにヘルパークラスをインポートします。

from mymodule.helpers import RandomFileName 

そしてそれを使います:

logo = models.ImageField(upload_to=RandomFileName('logos'))

参照: https://coderwall.com/p/hfgoiw/give-imagefield-uploads-a-unique-name-to-avoid-file-overwrites

12
Raptor

Django 1.6.6、1.5.9、および1.4.14以前は、 get_avaialable_name 関数は、アンダースコアを追加することで、ファイルに自動的に一意の名前を付けます。たとえば、「test.jpg」というファイルと「test.jpg」という別のファイルをサーバーに保存すると、最初のファイルはtest.jpg、2番目のファイルはtest_1.jpgという名前になります。

悲しいかな、それはマシンにDDOSを実行するためのベクトルであることが判明しました。保存する数千のゼロバイトファイルを送信し、それぞれが数千の以前のファイルをチェックして名前を確認します。

ドキュメントを参照 のように、新しいシステムはこの問題を修正するためにアンダースコアの後に7つのランダムな数字を追加します。

10
mlissner

この回答の執筆時点では、これを実現するために特別なことを行う必要はもうないようです。静的なupload_toプロパティを使用してFileFieldを設定すると、Djangoストレージシステムが自動的に命名を管理するため、重複したファイル名がアップロードされた場合、Djangoがランダムに複製の新しい一意のファイル名を生成します。

Django 1.10で動作します。

3
M. Ryan

独自のFileFieldを書いて上書きgenerate_filename

例えば:

class UniqueNameFileField(FileField):
    def generate_filename(self, instance, filename):
        _, ext = os.path.splitext(filename) 
        name = f'{uuid.uuid4().hex}{ext}'
        return super().generate_filename(instance, name)
0
D.W

写真がアップロードされた日付/時刻とファイル名を連結し、次に hashlib を使用してメッセージダイジェストを作成しませんか?それはあなたにユニークなファイル名を与えるはずです。

または、一意のファイル名を作成する きちんとした小さなスニペット を再利用し、そのファイルへの完全パスをハッシュ呼び出しへの入力として使用することもできます。これにより、ファイルにマップできる一意の一定長の文字列が得られます。

0
Jon Cage

Djangoは一意のファイル名を自動的に適用します。ファイルがすでに存在する場合、7つの一意の文字がファイル名に追加されます

Django 2.2でテスト済み

0
Aissam Jadli