2

私はDjangoImageFieldを持つクラスを持っていて、そのフィールドのupload_to関数を格納するための2つの選択肢のどちらかを決めるのに苦労しています。最初のアプローチは非常に簡単です。関数はモジュールレベルで定義されています( https://stackoverflow.com/a/1190866/790075、https://stackoverflow.com/a/3091864/790075参照):

def get_car_photo_file_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext) # chance of collision <1e-50
    return os.path.join('uploads/cars/photos', filename)

class CarPhoto(models.Model):
    photo = models.ImageField(upload_to=get_car_photo_file_path)

これは単純で理解しやすいですが、実際にはCarPhotoクラスにのみ関連する関数を追加することにより、モジュールスコープを汚染します。

2番目のアプローチでは、呼び出し可能クラスパターンを使用して、関数をCarPhotoクラスとより密接に関連付けます。これにより、upload_to関数はモジュールスコープの外に移動しますが、不必要に複雑に感じられます。

class CarPhoto(models.Model):
    class getCarPhotoFilePath():
        # Either use this pattern or associate function with module instead of this class
        def __call__(self, instance, filename):
            ext = filename.split('.')[-1]
            filename = "%s.%s" % (uuid.uuid4(), ext) # chance of collision <1e-50
            return os.path.join('uploads/cars/photos', filename)

    photo = models.ImageField(upload_to=getCarPhotoFilePath())

@staticmethod@classmethodデコレータを使用するための提案を見てきましたが( https://stackoverflow.com/a/9264153/790075を参照)、これを実行すると、関数が実行されず、ファイル名が次のようになります/path/to/file/<classmethod object>。ファイルパスに埋め込まれたオブジェクト。これは確かに意図されたものではありません。

これらのどれが好ましいパターンですか?もっと良い方法はありますか?

4

3 に答える 3

1

次のことをお勧めします。

import this

私にとって、これは次のように述べているZen of Pythonのセクションに該当します。

Simple is better than complex.
Complex is better than complicated.

あなたのシンプルなソリューションの方が優れていると思います。しかし、あなたのコンプレックスは複雑すぎるとは感じません。おそらくどちらでも大丈夫だと思います。ちょうど私の2セント。

于 2012-10-01T14:23:25.560 に答える
0

現在、私が使用しているコードには、最も単純なもののバリエーションがあります。唯一の違いは、関数は内部使用を目的としているため、_接頭辞が付いていることです。

def _get_car_photo_file_path(instance, filename):
    [...]

class CarPhoto(models.Model):
    photo = models.ImageField(upload_to=_get_car_photo_file_path)

ただし、これはよりPythonic(またはより多くのOOP)になると思います。

class CarPhoto(models.Model):

    @staticmethod
    def _get_file_path(instance, filename):
        [...]

    photo = models.ImageField(upload_to=_get_file_path) 
于 2012-10-02T16:42:12.957 に答える
0

名前の汚染を防ぐための命名規則があります。

  • 関数を内部としてマークするために使用_get_car_photo_file_pathします (非表示ではありません);
  • クラス外からの__get_car_photo_file_path アクセスを防ぐために使用します。

このような classmethod または staticmethod をCarPhotoクラスに追加できます。これは、呼び出し可能なクラスを追加するよりも簡単です (後者は、1 つのメソッドのために匿名クラスを定義する Java の方法を思い起こさせます)。

名前は、それが実装の詳細であり、インターフェースの一部ではないことを明確に示す_get_car_photo_file_pathため、クラスの名前空間の汚染を防ぎます。のメソッドCarPhotoであるため、この関数はモジュールの名前空間を汚染しません。

于 2012-10-01T17:00:52.493 に答える