这个python函数如何获取其参数?

时间:2014-08-07 14:46:12

标签: python django amazon-s3 django-models

我按照本教程将amazon S3应用到我的django应用程序中: http://djangotricks.blogspot.com/2013/12/how-to-store-your-media-files-in-amazon.html

在其中,他定义了一个函数upload_avatar_to,它有两个参数:

def upload_avatar_to(instance, filename):
    import os
    from django.utils.timezone import now
    filename_base, filename_ext = os.path.splitext(filename)
    return 'profiles/%s%s' % (
        now().strftime("%Y%m%d%H%M%S"),
        filename_ext.lower(),
    )

然而,当他打电话给他时,他没有提供任何参数:

class Profile(models.Model):
    # ...
    avatar = models.ImageField(_("Avatar"), upload_to=upload_avatar_to, blank=True)
    # ...

如果在调用时没有提供实例和文件名,该函数如何获取?

我想在函数调用中添加一个额外的参数,比如" foldername"。我怎么能这样做?

3 个答案:

答案 0 :(得分:1)

在Django文档中有明确记录,upload_to可以是可调用的: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.FileField.upload_to

根据官方文件:

这也可以是一个可调用的函数,例如一个函数,它将被调用以获取上传路径,包括文件名。 此callable必须能够接受两个参数,并返回一个Unix风格的路径(带有正斜杠)以传递给存储系统。将传递的两个参数是:

<强>实例
定义FileField的模型实例。更具体地说,这是附加当前文件的特定实例。

在大多数情况下,此对象尚未保存到数据库,因此如果它使用默认的AutoField,则可能还没有其主键字段的值。

<强>文件名
最初提供给文件的文件名。在确定最终目的地路径时,可能会或可能不会考虑这一点。

答案 1 :(得分:0)

这看起来不像函数upload_avatar_to()的调用,而是将函数本身作为参数传递,因此可以在头像中调用它。

答案 2 :(得分:0)

正在发生的事情是Django正在最后一行代码中传递函数对象 - 当时没有调用该函数。稍后将在ImageField构造函数中调用该函数,在该构造函数中将为其提供instancefilename参数并返回一个值。这很容易做到,因为函数是Python中的第一类对象。

正如petkostas在他的链接中显示的那样,你提供的函数必须正好使用两个参数,实例和文件名。不过,我们可以解决这个问题!

你可以做的是为upload_avatar_to创建一个函数包装器,它允许你提供额外的参数,同时仍然符合Django的要求。看看这个:

def upload_to_wrapper(foldername):
  def wrapper(instance, filename):
    upload_avatar_to(instance, filename, foldername)
  return wrapper

然后你会像这样定义你的函数:

def upload_avatar_to(instance, filename, foldername):
  # Do your thing.

最后,这是您要拨打的最后一行,以及您提供所需foldername的地方:

avatar = models.ImageField(_("Avatar"), upload_to=upload_to_wrapper(foldername), blank=True)

基本上,upload_to_wrapper会返回upload_avatar_to对象的修改版本,该对象已提供foldername,且只需要instancefilename指定。这允许您解决Django的要求。该特定ImageField函数要求您提供一个取instancefilename的函数对象,但这正是upload_to_wrapper返回的函数,因此您可以继续使用。