When saving, how can you check if a field has changed?

前端 未结 25 1714
鱼传尺愫
鱼传尺愫 2020-11-22 07:15

In my model I have :

class Alias(MyBaseModel):
    remote_image = models.URLField(max_length=500, null=True, help_text=\"A URL that is downloaded and cached          


        
相关标签:
25条回答
  • 2020-11-22 07:25

    This works for me in Django 1.8

    def clean(self):
        if self.cleaned_data['name'] != self.initial['name']:
            # Do something
    
    0 讨论(0)
  • 2020-11-22 07:26

    Essentially, you want to override the __init__ method of models.Model so that you keep a copy of the original value. This makes it so that you don't have to do another DB lookup (which is always a good thing).

    class Person(models.Model):
        name = models.CharField()
    
        __original_name = None
    
        def __init__(self, *args, **kwargs):
            super(Person, self).__init__(*args, **kwargs)
            self.__original_name = self.name
    
        def save(self, force_insert=False, force_update=False, *args, **kwargs):
            if self.name != self.__original_name:
                # name changed - do something here
    
            super(Person, self).save(force_insert, force_update, *args, **kwargs)
            self.__original_name = self.name
    
    0 讨论(0)
  • 2020-11-22 07:29

    Another late answer, but if you're just trying to see if a new file has been uploaded to a file field, try this: (adapted from Christopher Adams's comment on the link http://zmsmith.com/2010/05/django-check-if-a-field-has-changed/ in zach's comment here)

    Updated link: https://web.archive.org/web/20130101010327/http://zmsmith.com:80/2010/05/django-check-if-a-field-has-changed/

    def save(self, *args, **kw):
        from django.core.files.uploadedfile import UploadedFile
        if hasattr(self.image, 'file') and isinstance(self.image.file, UploadedFile) :
            # Handle FileFields as special cases, because the uploaded filename could be
            # the same as the filename that's already there even though there may
            # be different file contents.
    
            # if a file was just uploaded, the storage model with be UploadedFile
            # Do new file stuff here
            pass
    
    0 讨论(0)
  • 2020-11-22 07:29

    If you do not find interest in overriding save method, you can do

      model_fields = [f.name for f in YourModel._meta.get_fields()]
      valid_data = {
            key: new_data[key]
            for key in model_fields
            if key in new_data.keys()
      }
    
      for (key, value) in valid_data.items():
            if getattr(instance, key) != value:
               print ('Data has changed')
    
            setattr(instance, key, value)
    
     instance.save()
    
    0 讨论(0)
  • 2020-11-22 07:30

    Since Django 1.8 released, you can use from_db classmethod to cache old value of remote_image. Then in save method you can compare old and new value of field to check if the value has changed.

    @classmethod
    def from_db(cls, db, field_names, values):
        new = super(Alias, cls).from_db(db, field_names, values)
        # cache value went from the base
        new._loaded_remote_image = values[field_names.index('remote_image')]
        return new
    
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if (self._state.adding and self.remote_image) or \
            (not self._state.adding and self._loaded_remote_image != self.remote_image):
            # If it is first save and there is no cached remote_image but there is new one, 
            # or the value of remote_image has changed - do your stuff!
    
    0 讨论(0)
  • 2020-11-22 07:34

    How about using David Cramer's solution:

    http://cramer.io/2010/12/06/tracking-changes-to-fields-in-django/

    I've had success using it like this:

    @track_data('name')
    class Mode(models.Model):
        name = models.CharField(max_length=5)
        mode = models.CharField(max_length=5)
    
        def save(self, *args, **kwargs):
            if self.has_changed('name'):
                print 'name changed'
    
        # OR #
    
        @classmethod
        def post_save(cls, sender, instance, created, **kwargs):
            if instance.has_changed('name'):
                print "Hooray!"
    
    0 讨论(0)
提交回复
热议问题