2

我有一个带有Django ImageField的类,我一直在努力在两种存储该字段upload_to功能的替代方案之间做出决定。第一种方法非常简单。该函数在模块级别定义(参见 https://stackoverflow.com/a/1190866/790075https://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 类相关的函数来污染模块范围。

在第二种方法中,我使用可调用类模式将函数与 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())

我已经看到了使用@staticmethodand@classmethod装饰器的建议(参见https://stackoverflow.com/a/9264153/790075),但我发现当我这样做时,函数永远不会执行,并且文件名最终看起来像:/path/to/file/<classmethod object>,使用方法嵌入在文件路径中的对象,这当然不是故意的!

以下哪个是首选模式?有没有更好的办法?

4

3 回答 3

1

我建议你:

import this

对我来说,这属于Python 的禅宗部分,说明:

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

我认为您的简单解决方案更好。但是,你的情结并不会感觉过于复杂。我想你可能会没事的。只是我的两分钱。

于 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 防止从课堂外访问它。

您可以在您的类中添加这样的类方法或静态方法CarPhoto,这比添加可调用类更简单(后者让我想起了 Java 为一种方法而定义匿名类的方式)。

该名称将清楚地表明这_get_car_photo_file_path是一个实现细节,而不是接口的一部分,从而防止污染类的命名空间。作为CarPhoto的方法,该函数不会污染模块的命名空间。

于 2012-10-01T17:00:52.493 回答