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

前端 未结 25 2298
鱼传尺愫
鱼传尺愫 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:35

    The mixin from @ivanlivski is great.

    I've extended it to

    • Ensure it works with Decimal fields.
    • Expose properties to simplify usage

    The updated code is available here: https://github.com/sknutsonsf/python-contrib/blob/master/src/django/utils/ModelDiffMixin.py

    To help people new to Python or Django, I'll give a more complete example. This particular usage is to take a file from a data provider and ensure the records in the database reflect the file.

    My model object:

    class Station(ModelDiffMixin.ModelDiffMixin, models.Model):
        station_name = models.CharField(max_length=200)
        nearby_city = models.CharField(max_length=200)
    
        precipitation = models.DecimalField(max_digits=5, decimal_places=2)
        # 
    
       def is_float_changed (self,v1, v2):
            ''' Compare two floating values to just two digit precision
            Override Default precision is 5 digits
            '''
            return abs (round (v1 - v2, 2)) > 0.01
    

    The class that loads the file has these methods:

    class UpdateWeather (object)
        # other methods omitted
    
        def update_stations (self, filename):
            # read all existing data 
            all_stations = models.Station.objects.all()
            self._existing_stations = {}
    
            # insert into a collection for referencing while we check if data exists
            for stn in all_stations.iterator():
                self._existing_stations[stn.id] = stn
    
            # read the file. result is array of objects in known column order
            data = read_tabbed_file(filename)
    
            # iterate rows from file and insert or update where needed
            for rownum in range(sh.nrows):
                self._update_row(sh.row(rownum));
    
            # now anything remaining in the collection is no longer active
            # since it was not found in the newest file
            # for now, delete that record
            # there should never be any of these if the file was created properly
            for stn in self._existing_stations.values():
                stn.delete()
                self._num_deleted = self._num_deleted+1
    
    
        def _update_row (self, rowdata):
            stnid = int(rowdata[0].value) 
            name = rowdata[1].value.strip()
    
            # skip the blank names where data source has ids with no data today
            if len(name) < 1:
                return
    
            # fetch rest of fields and do sanity test
            nearby_city = rowdata[2].value.strip()
            precip = rowdata[3].value
    
            if stnid in self._existing_stations:
                stn = self._existing_stations[stnid]
                del self._existing_stations[stnid]
                is_update = True;
            else:
                stn = models.Station()
                is_update = False;
    
            # object is new or old, don't care here            
            stn.id = stnid
            stn.station_name = name;
            stn.nearby_city = nearby_city
            stn.precipitation = precip
    
            # many other fields updated from the file 
    
            if is_update == True:
    
                # we use a model mixin to simplify detection of changes
                # at the cost of extra memory to store the objects            
                if stn.has_changed == True:
                    self._num_updated = self._num_updated + 1;
                    stn.save();
            else:
                self._num_created = self._num_created + 1;
                stn.save()
    

提交回复
热议问题