Ticket #7159: loaddata-delete-2.diff

File loaddata-delete-2.diff, 5.3 KB (added by Graham King <graham@…>, 7 years ago)

Patch updated for Django r7899

  • django/core/management/commands/loaddata.py

     
    1414        make_option('--verbosity', action='store', dest='verbosity', default='1',
    1515            type='choice', choices=['0', '1', '2'],
    1616            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
     17        make_option('--delete', action='store_true', dest='delete', default=False,
     18            help='Deletes any items in the database which are not in the fixture'),
    1719    )
    1820    help = 'Installs the named fixture(s) in the database.'
    1921    args = "fixture [fixture ...]"
     22   
     23    def remove_objects_not_in(self, objects_to_keep, verbosity):
     24        """
     25        Deletes all the objects in the database that are not in objects_to_keep.
     26        - objects_to_keep: A map where the keys are classes, and the values are a
     27         set of the objects of that class we should keep.
     28        """
     29        for class_ in objects_to_keep.keys():
    2030
     31            current = class_.objects.all()
     32            current_ids = set( [x.id for x in current] )
     33            keep_ids = set( [x.id for x in objects_to_keep[class_]] )
     34
     35            remove_these_ones = current_ids.difference(keep_ids)
     36            if remove_these_ones:
     37
     38                for obj in current:
     39                    if obj.id in remove_these_ones:
     40                        obj.delete()
     41                        if verbosity >= 2:
     42                            print "Deleted object: "+ unicode(obj)
     43
     44            if verbosity > 0 and remove_these_ones:
     45                num_deleted = len(remove_these_ones)
     46                if num_deleted > 1:
     47                    type_deleted = unicode(class_._meta.verbose_name_plural)
     48                else:
     49                    type_deleted = unicode(class_._meta.verbose_name)
     50
     51                print "Deleted "+ str(num_deleted) +" "+ type_deleted
     52
    2153    def handle(self, *fixture_labels, **options):
    2254        from django.db.models import get_apps
    2355        from django.core import serializers
     
    2860
    2961        verbosity = int(options.get('verbosity', 1))
    3062        show_traceback = options.get('traceback', False)
    31 
     63        is_delete = options.get('delete', False)
     64       
    3265        # Keep a count of the installed objects and fixtures
    3366        fixture_count = 0
    3467        object_count = 0
     
    104137                                print "Installing %s fixture '%s' from %s." % \
    105138                                    (format, fixture_name, humanize(fixture_dir))
    106139                            try:
     140                                objects_to_keep = {}
    107141                                objects = serializers.deserialize(format, fixture)
    108142                                for obj in objects:
    109143                                    object_count += 1
    110144                                    objects_per_fixture[-1] += 1
    111                                     models.add(obj.object.__class__)
     145
     146                                    class_ = obj.object.__class__
     147                                    if not class_ in objects_to_keep:
     148                                        objects_to_keep[class_] = set()
     149                                    objects_to_keep[class_].add(obj.object)
     150                                   
     151                                    models.add(class_)
    112152                                    obj.save()
     153
     154                                if is_delete:
     155                                    self.remove_objects_not_in(objects_to_keep, verbosity)
     156
    113157                                label_found = True
    114158                            except (SystemExit, KeyboardInterrupt):
    115159                                raise
  • tests/modeltests/fixtures/models.py

     
    5454# object list is unaffected
    5555>>> Article.objects.all()
    5656[<Article: XML identified as leading cause of cancer>, <Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker on TV is great!>, <Article: Python program becomes self aware>]
     57
     58# Delete two existing objects
     59>>> management.call_command('loaddata', 'fixture4.json', verbosity=0, delete=True)
     60>>> Article.objects.all()
     61[<Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker on TV is great!>]
    5762"""}
    5863
    5964# Database flushing does not work on MySQL with the default storage engine
  • docs/django-admin.txt

     
    387387Example usage::
    388388
    389389    django-admin.py loaddata --verbosity=2
     390   
     391**New in Django development version**
     392--delete
     393~~~~~~~~
    390394
     395Deletes any objects in the database which are not in the fixtures. If you run ``loaddata``
     396with ``--delete``, after the operation the database will exactly match the contents
     397of the fixtures.
     398If you do not specify ``--delete`` new objects only present in the fixture will be created in
     399the database, objects present in both will be updated, but no data will be removed from
     400the database.
     401
    391402makemessages
    392403------------
    393404
Back to Top