Ticket #13772: pre_save.patch

File pre_save.patch, 6.0 KB (added by George Sakkis, 14 years ago)

Patch against r13861

  • django/db/models/base.py

    diff -r a853880b25d1 django/db/models/base.py
    a b  
    454454        else:
    455455            meta = cls._meta
    456456
     457        pk_val = self._get_pk_val(meta)
     458        pk_set = pk_val is not None
     459        manager = cls._base_manager
     460        record_exists = pk_set and manager.using(using).filter(pk=pk_val).exists()
    457461        if origin and not meta.auto_created:
    458             signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using)
     462            signals.pre_save.send(sender=origin, instance=self, raw=raw,
     463                                  exists=record_exists, using=using)
    459464
    460465        # If we are in a raw save, save the object exactly as presented.
    461466        # That means that we don't try to be smart about saving attributes
     
    484489
    485490        if not meta.proxy:
    486491            non_pks = [f for f in meta.local_fields if not f.primary_key]
    487 
    488             # First, try an UPDATE. If that doesn't update anything, do an INSERT.
    489             pk_val = self._get_pk_val(meta)
    490             pk_set = pk_val is not None
    491             record_exists = True
    492             manager = cls._base_manager
    493             if pk_set:
    494                 # Determine whether a record with the primary key already exists.
    495                 if (force_update or (not force_insert and
    496                         manager.using(using).filter(pk=pk_val).exists())):
    497                     # It does already exist, so do an UPDATE.
    498                     if force_update or non_pks:
    499                         values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
    500                         rows = manager.using(using).filter(pk=pk_val)._update(values)
    501                         if force_update and not rows:
    502                             raise DatabaseError("Forced update did not affect any rows.")
    503                 else:
    504                     record_exists = False
    505             if not pk_set or not record_exists:
     492            can_force_update = force_update and pk_set
     493            can_update = record_exists and not force_insert
     494            if can_force_update or (can_update and non_pks):
     495                values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
     496                rows = manager.using(using).filter(pk=pk_val)._update(values)
     497                if force_update and not rows:
     498                    raise DatabaseError("Forced update did not affect any rows.")
     499            elif not (can_force_update or can_update):
    506500                if meta.order_with_respect_to:
    507501                    # If this is a model with an order_with_respect_to
    508502                    # autopopulate the _order field
     
    519513                    values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True), connection=connection))
    520514                        for f in meta.local_fields]
    521515
    522                 record_exists = False
    523 
    524516                update_pk = bool(meta.has_auto_field and not pk_set)
    525517                if values:
    526518                    # Create a new record.
  • django/db/models/signals.py

    diff -r a853880b25d1 django/db/models/signals.py
    a b  
    55pre_init = Signal(providing_args=["instance", "args", "kwargs"])
    66post_init = Signal(providing_args=["instance"])
    77
    8 pre_save = Signal(providing_args=["instance", "raw", "using"])
     8pre_save = Signal(providing_args=["instance", "raw", "exists", "using"])
    99post_save = Signal(providing_args=["instance", "raw", "created", "using"])
    1010
    1111pre_delete = Signal(providing_args=["instance", "using"])
  • tests/modeltests/signals/models.py

    diff -r a853880b25d1 tests/modeltests/signals/models.py
    a b  
    2121
    2222def pre_save_test(signal, sender, instance, **kwargs):
    2323    print 'pre_save signal,', instance
     24    if 'exists' in kwargs:
     25        if kwargs['exists']:
     26            print 'Exists'
     27        else:
     28            print 'Does not exist'
    2429    if kwargs.get('raw'):
    2530        print 'Is raw'
    2631
     
    7378>>> p1 = Person(first_name='John', last_name='Smith')
    7479>>> p1.save()
    7580pre_save signal, John Smith
     81Does not exist
    7682pre_save signal decorator, John Smith
    7783post_save signal, John Smith
    7884Is created
     
    8086>>> p1.first_name = 'Tom'
    8187>>> p1.save()
    8288pre_save signal, Tom Smith
     89Exists
    8390pre_save signal decorator, Tom Smith
    8491post_save signal, Tom Smith
    8592Is updated
     
    8895>>> c1 = Car(make="Volkswagon", model="Passat")
    8996>>> c1.save()
    9097pre_save signal, Volkswagon Passat
     98Does not exist
    9199pre_save signal decorator, Volkswagon Passat
    92100pre_save signal decorator sender, Volkswagon Passat
    93101post_save signal, Volkswagon Passat
     
    96104# Calling an internal method purely so that we can trigger a "raw" save.
    97105>>> p1.save_base(raw=True)
    98106pre_save signal, Tom Smith
     107Exists
    99108Is raw
    100109pre_save signal decorator, Tom Smith
    101110post_save signal, Tom Smith
     
    112121>>> p2.id = 99999
    113122>>> p2.save()
    114123pre_save signal, James Jones
     124Does not exist
    115125pre_save signal decorator, James Jones
    116126post_save signal, James Jones
    117127Is created
     
    119129>>> p2.id = 99998
    120130>>> p2.save()
    121131pre_save signal, James Jones
     132Does not exist
    122133pre_save signal decorator, James Jones
    123134post_save signal, James Jones
    124135Is created
  • tests/regressiontests/signals_regress/models.py

    diff -r a853880b25d1 tests/regressiontests/signals_regress/models.py
    a b  
    1919
    2020def pre_save_test(signal, sender, instance, **kwargs):
    2121    print 'pre_save signal,', instance
     22    if 'exists' in kwargs:
     23        if kwargs['exists']:
     24            print 'Exists'
     25        else:
     26            print 'Does not exist'
    2227    if kwargs.get('raw'):
    2328        print 'Is raw'
    2429
     
    5762>>> a1 = Author(name='Neal Stephenson')
    5863>>> a1.save()
    5964pre_save signal, Neal Stephenson
     65Does not exist
    6066post_save signal, Neal Stephenson
    6167Is created
    6268
    6369>>> b1 = Book(name='Snow Crash')
    6470>>> b1.save()
    6571pre_save signal, Snow Crash
     72Does not exist
    6673post_save signal, Snow Crash
    6774Is created
    6875
Back to Top