在我的模型中我有:

class Alias(MyBaseModel):
remote_image = models.URLField(
    max_length=500, null=True,
    help_text='''
        A URL that is downloaded and cached for the image.
        Only used when the alias is made
    '''
)
    image = models.ImageField(
        upload_to='alias', default='alias-default.png',
        help_text="An image representing the alias"
    )

    
    def save(self, *args, **kw):
        if (not self.image or self.image.name == 'alias-default.png') and self.remote_image :
            try :
                data = utils.fetch(self.remote_image)
                image = StringIO.StringIO(data)
                image = Image.open(image)
                buf = StringIO.StringIO()
                image.save(buf, format='PNG')
                self.image.save(
                    hashlib.md5(self.string_id).hexdigest() + ".png", ContentFile(buf.getvalue())
                )
            except IOError :
                pass

这在remote_image第一次改变的时候工作得很好。

当有人修改了别名上的remote_image时,我如何获取一个新的图像?其次,是否有更好的方法来缓存远程映像?


当前回答

改进所有领域的@josh答案:

class Person(models.Model):
  name = models.CharField()

def __init__(self, *args, **kwargs):
    super(Person, self).__init__(*args, **kwargs)
    self._original_fields = dict([(field.attname, getattr(self, field.attname))
        for field in self._meta.local_fields if not isinstance(field, models.ForeignKey)])

def save(self, *args, **kwargs):
  if self.id:
    for field in self._meta.local_fields:
      if not isinstance(field, models.ForeignKey) and\
        self._original_fields[field.name] != getattr(self, field.name):
        # Do Something    
  super(Person, self).save(*args, **kwargs)

澄清一下,getattr的工作是获取像person.name这样带字符串的字段(即getattr(person, "name"))

其他回答

改进所有领域的@josh答案:

class Person(models.Model):
  name = models.CharField()

def __init__(self, *args, **kwargs):
    super(Person, self).__init__(*args, **kwargs)
    self._original_fields = dict([(field.attname, getattr(self, field.attname))
        for field in self._meta.local_fields if not isinstance(field, models.ForeignKey)])

def save(self, *args, **kwargs):
  if self.id:
    for field in self._meta.local_fields:
      if not isinstance(field, models.ForeignKey) and\
        self._original_fields[field.name] != getattr(self, field.name):
        # Do Something    
  super(Person, self).save(*args, **kwargs)

澄清一下,getattr的工作是获取像person.name这样带字符串的字段(即getattr(person, "name"))

虽然这实际上并没有回答你的问题,但我会以不同的方式来讨论这个问题。

成功保存本地副本后,只需清除remote_image字段。然后在保存方法中,只要remote_image不为空,就可以随时更新图像。

如果您想保留对url的引用,您可以使用一个不可编辑的布尔字段来处理缓存标志,而不是使用remote_image字段本身。

这在Django 1.8中是适用的

def clean(self):
    if self.cleaned_data['name'] != self.initial['name']:
        # Do something

注意,字段更改跟踪在django-model-utils中是可用的。

https://django-model-utils.readthedocs.org/en/latest/index.html

作为SmileyChris回答的扩展,您可以为last_updated的模型添加一个datetime字段,并在检查更改之前为您将让它达到的最大年龄设置某种限制