'Returns the difference between the old and new sets of models as a 5-tuple:
added_models, deleted_models, added_fields, deleted_fields, changed_fields'

def get_changes(self):

    deleted_models = set()
    for key in self.old_defs:
        if (key not in self.new_defs):
            (old_fields, old_meta, old_m2ms) = self.split_model_def(self.old_orm[key], self.old_defs[key])
            if (old_meta.get('managed', 'True') != 'False'):
                (yield ('DeleteModel', {'model': self.old_orm[key], 'model_def': old_fields}))
                for fieldname in old_m2ms:
                    field = self.old_orm[((key + ':') + fieldname)]
                    if auto_through(field):
                        (yield ('DeleteM2M', {'model': self.old_orm[key], 'field': field}))
                for (attr, operation) in (('unique_together', 'DeleteUnique'), ('index_together', 'DeleteIndex')):
                    together = eval(old_meta.get(attr, '[]'))
                    if together:
                        if isinstance(together[0], string_types):
                            together = [together]
                        for fields in together:
                            (yield (operation, {'model': self.old_orm[key], 'fields': [self.old_orm[key]._meta.get_field_by_name(x)[0] for x in fields]}))
            deleted_models.add(key)
    for key in self.new_defs:
        if (key not in self.old_defs):
            (new_fields, new_meta, new_m2ms) = self.split_model_def(self.current_model_from_key(key), self.new_defs[key])
            if (new_meta.get('managed', 'True') != 'False'):
                (yield ('AddModel', {'model': self.current_model_from_key(key), 'model_def': new_fields}))
                for fieldname in new_m2ms:
                    field = self.current_field_from_key(key, fieldname)
                    if auto_through(field):
                        (yield ('AddM2M', {'model': self.current_model_from_key(key), 'field': field}))
                for (attr, operation) in (('unique_together', 'AddUnique'), ('index_together', 'AddIndex')):
                    together = eval(new_meta.get(attr, '[]'))
                    if together:
                        if isinstance(together[0], string_types):
                            together = [together]
                        for fields in together:
                            (yield (operation, {'model': self.current_model_from_key(key), 'fields': [self.current_model_from_key(key)._meta.get_field_by_name(x)[0] for x in fields]}))
    for key in self.old_defs:
        if (key not in deleted_models):
            (old_fields, old_meta, old_m2ms) = self.split_model_def(self.old_orm[key], self.old_defs[key])
            (new_fields, new_meta, new_m2ms) = self.split_model_def(self.current_model_from_key(key), self.new_defs[key])
            if (new_meta.get('managed', 'True') == 'False'):
                continue
            for fieldname in old_fields:
                if (fieldname not in new_fields):
                    field = self.old_orm[((key + ':') + fieldname)]
                    field_allowed = True
                    for field_type in self.IGNORED_FIELD_TYPES:
                        if isinstance(field, field_type):
                            field_allowed = False
                    if field_allowed:
                        (yield ('DeleteField', {'model': self.old_orm[key], 'field': field, 'field_def': old_fields[fieldname]}))
            for fieldname in new_fields:
                if (fieldname not in old_fields):
                    field = self.current_field_from_key(key, fieldname)
                    field_allowed = True
                    for field_type in self.IGNORED_FIELD_TYPES:
                        if isinstance(field, field_type):
                            field_allowed = False
                    if field_allowed:
                        (yield ('AddField', {'model': self.current_model_from_key(key), 'field': field, 'field_def': new_fields[fieldname]}))
            for fieldname in old_m2ms:
                if (fieldname not in new_m2ms):
                    field = self.old_orm[((key + ':') + fieldname)]
                    if auto_through(field):
                        (yield ('DeleteM2M', {'model': self.old_orm[key], 'field': field}))
            for fieldname in new_m2ms:
                if (fieldname not in old_m2ms):
                    field = self.current_field_from_key(key, fieldname)
                    if auto_through(field):
                        (yield ('AddM2M', {'model': self.current_model_from_key(key), 'field': field}))
            for fieldname in set(old_fields).intersection(set(new_fields)):
                if self.different_attributes(remove_useless_attributes(old_fields[fieldname], True, True), remove_useless_attributes(new_fields[fieldname], True, True)):
                    (yield ('ChangeField', {'model': self.current_model_from_key(key), 'old_field': self.old_orm[((key + ':') + fieldname)], 'new_field': self.current_field_from_key(key, fieldname), 'old_def': old_fields[fieldname], 'new_def': new_fields[fieldname]}))
                old_field = self.old_orm[((key + ':') + fieldname)]
                new_field = self.current_field_from_key(key, fieldname)
                if ((not old_field.db_index) and new_field.db_index):
                    (yield ('AddIndex', {'model': self.current_model_from_key(key), 'fields': [new_field]}))
                if (old_field.db_index and (not new_field.db_index)):
                    (yield ('DeleteIndex', {'model': self.old_orm[key], 'fields': [old_field]}))
                if (old_field.unique != new_field.unique):
                    if new_field.unique:
                        (yield ('AddUnique', {'model': self.current_model_from_key(key), 'fields': [new_field]}))
                    else:
                        (yield ('DeleteUnique', {'model': self.old_orm[key], 'fields': [old_field]}))
            for fieldname in set(old_m2ms).intersection(set(new_m2ms)):
                old_field = self.old_orm[((key + ':') + fieldname)]
                new_field = self.current_field_from_key(key, fieldname)
                if (auto_through(old_field) and (not auto_through(new_field))):
                    (yield ('DeleteM2M', {'model': self.old_orm[key], 'field': old_field}))
                if ((not auto_through(old_field)) and auto_through(new_field)):
                    (yield ('AddM2M', {'model': self.current_model_from_key(key), 'field': new_field}))
            for (attr, add_operation, del_operation) in (('unique_together', 'AddUnique', 'DeleteUnique'), ('index_together', 'AddIndex', 'DeleteIndex')):
                old_together = eval(old_meta.get(attr, '[]'))
                new_together = eval(new_meta.get(attr, '[]'))
                if (old_together and isinstance(old_together[0], string_types)):
                    old_together = [old_together]
                if (new_together and isinstance(new_together[0], string_types)):
                    new_together = [new_together]
                old_together = frozenset((tuple(o) for o in old_together))
                new_together = frozenset((tuple(n) for n in new_together))
                disappeared = old_together.difference(new_together)
                appeared = new_together.difference(old_together)
                for item in disappeared:
                    (yield (del_operation, {'model': self.old_orm[key], 'fields': [self.old_orm[((key + ':') + x)] for x in item]}))
                for item in appeared:
                    (yield (add_operation, {'model': self.current_model_from_key(key), 'fields': [self.current_field_from_key(key, x) for x in item]}))
