Ejemplo n.º 1
0
        def add(self, *objs, bulk=True):
            self._remove_prefetched_objects()
            db = router.db_for_write(self.model, instance=self.instance)

            def check_and_update_obj(obj):
                if not isinstance(obj, self.model):
                    raise TypeError("'%s' instance expected, got %r" %
                                    (self.model._meta.object_name, obj))
                setattr(obj, self.content_type_field_name, self.content_type)
                setattr(obj, self.object_id_field_name, self.pk_val)

            if bulk:
                pks = []
                for obj in objs:
                    if obj._state.adding or obj._state.db != db:
                        raise ValueError(
                            "%r instance isn't saved. Use bulk=False or save "
                            "the object first." % obj)
                    check_and_update_obj(obj)
                    pks.append(obj.pk)

                self.model._base_manager.using(db).filter(pk__in=pks).update(
                    **{
                        self.content_type_field_name: self.content_type,
                        self.object_id_field_name: self.pk_val,
                    })
            else:
                with transaction.atomic(using=db, savepoint=False):
                    for obj in objs:
                        check_and_update_obj(obj)
                        obj.save()
Ejemplo n.º 2
0
 def test_sql_insert_compiler_return_id_attribute(self):
     """
     Regression test for #14019: SQLInsertCompiler.as_sql() failure
     """
     db = router.db_for_write(Party)
     query = InsertQuery(Party)
     query.insert_values([Party._meta.fields[0]], [], raw=False)
     # this line will raise an AttributeError without the accompanying fix
     query.get_compiler(using=db).as_sql()
Ejemplo n.º 3
0
 def _clear(self, queryset, bulk):
     self._remove_prefetched_objects()
     db = router.db_for_write(self.model, instance=self.instance)
     queryset = queryset.using(db)
     if bulk:
         # `QuerySet.delete()` creates its own atomic block which
         # contains the `pre_delete` and `post_delete` signal handlers.
         queryset.delete()
     else:
         with transaction.atomic(using=db, savepoint=False):
             for obj in queryset:
                 obj.delete()
Ejemplo n.º 4
0
    def handle(self, **options):
        db = options['database']
        interactive = options['interactive']
        verbosity = options['verbosity']

        for app_config in apps.get_app_configs():
            content_types, app_models = get_contenttypes_and_models(app_config, db, ContentType)
            to_remove = [
                ct for (model_name, ct) in content_types.items()
                if model_name not in app_models
            ]
            # Confirm that the content type is stale before deletion.
            using = router.db_for_write(ContentType)
            if to_remove:
                if interactive:
                    ct_info = []
                    for ct in to_remove:
                        ct_info.append('    - Content type for %s.%s' % (ct.app_label, ct.model))
                        collector = NoFastDeleteCollector(using=using)
                        collector.collect([ct])

                        for obj_type, objs in collector.data.items():
                            if objs != {ct}:
                                ct_info.append('    - %s %s object(s)' % (
                                    len(objs),
                                    obj_type._meta.label,
                                ))
                    content_type_display = '\n'.join(ct_info)
                    self.stdout.write("""Some content types in your database are stale and can be deleted.
Any objects that depend on these content types will also be deleted.
The content types and dependent objects that would be deleted are:

%s

This list doesn't include any cascade deletions to data outside of Django's
models (uncommon).

Are you sure you want to delete these content types?
If you're unsure, answer 'no'.\n""" % content_type_display)
                    ok_to_delete = input("Type 'yes' to continue, or 'no' to cancel: ")
                else:
                    ok_to_delete = 'yes'

                if ok_to_delete == 'yes':
                    for ct in to_remove:
                        if verbosity >= 2:
                            self.stdout.write("Deleting stale content type '%s | %s'" % (ct.app_label, ct.model))
                        ct.delete()
                else:
                    if verbosity >= 2:
                        self.stdout.write("Stale content types remain.")
Ejemplo n.º 5
0
    def _base_delete_many(self, keys):
        if not keys:
            return

        db = router.db_for_write(self.cache_model_class)
        connection = connections[db]
        quote_name = connection.ops.quote_name
        table = quote_name(self._table)

        with connection.cursor() as cursor:
            cursor.execute(
                'DELETE FROM %s WHERE %s IN (%s)' % (
                    table,
                    quote_name('cache_key'),
                    ', '.join(['%s'] * len(keys)),
                ),
                keys,
            )
Ejemplo n.º 6
0
        def set(self, objs, *, bulk=True, clear=False):
            # Force evaluation of `objs` in case it's a queryset whose value
            # could be affected by `manager.clear()`. Refs #19816.
            objs = tuple(objs)

            db = router.db_for_write(self.model, instance=self.instance)
            with transaction.atomic(using=db, savepoint=False):
                if clear:
                    self.clear()
                    self.add(*objs, bulk=bulk)
                else:
                    old_objs = set(self.using(db).all())
                    new_objs = []
                    for obj in objs:
                        if obj in old_objs:
                            old_objs.remove(obj)
                        else:
                            new_objs.append(obj)

                    self.remove(*old_objs)
                    self.add(*new_objs, bulk=bulk)
Ejemplo n.º 7
0
 def clear(self):
     db = router.db_for_write(self.cache_model_class)
     connection = connections[db]
     table = connection.ops.quote_name(self._table)
     with connection.cursor() as cursor:
         cursor.execute('DELETE FROM %s' % table)
Ejemplo n.º 8
0
    def _base_set(self, mode, key, value, timeout=DEFAULT_TIMEOUT):
        timeout = self.get_backend_timeout(timeout)
        db = router.db_for_write(self.cache_model_class)
        connection = connections[db]
        quote_name = connection.ops.quote_name
        table = quote_name(self._table)

        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM %s" % table)
            num = cursor.fetchone()[0]
            now = timezone.now()
            now = now.replace(microsecond=0)
            if timeout is None:
                exp = datetime.max
            elif settings.USE_TZ:
                exp = datetime.utcfromtimestamp(timeout)
            else:
                exp = datetime.fromtimestamp(timeout)
            exp = exp.replace(microsecond=0)
            if num > self._max_entries:
                self._cull(db, cursor, now)
            pickled = pickle.dumps(value, self.pickle_protocol)
            # The DB column is expecting a string, so make sure the value is a
            # string, not bytes. Refs #19274.
            b64encoded = base64.b64encode(pickled).decode('latin1')
            try:
                # Note: typecasting for datetimes is needed by some 3rd party
                # database backends. All core backends work without typecasting,
                # so be careful about changes here - test suite will NOT pick
                # regressions.
                with transaction.atomic(using=db):
                    cursor.execute(
                        'SELECT %s, %s FROM %s WHERE %s = %%s' % (
                            quote_name('cache_key'),
                            quote_name('expires'),
                            table,
                            quote_name('cache_key'),
                        ), [key])
                    result = cursor.fetchone()

                    if result:
                        current_expires = result[1]
                        expression = models.Expression(
                            output_field=models.DateTimeField())
                        for converter in (
                                connection.ops.get_db_converters(expression) +
                                expression.get_db_converters(connection)):
                            if func_supports_parameter(
                                    converter,
                                    'context'):  # RemovedInDjango30Warning
                                current_expires = converter(
                                    current_expires, expression, connection,
                                    {})
                            else:
                                current_expires = converter(
                                    current_expires, expression, connection)

                    exp = connection.ops.adapt_datetimefield_value(exp)
                    if result and mode == 'touch':
                        cursor.execute(
                            'UPDATE %s SET %s = %%s WHERE %s = %%s' %
                            (table, quote_name('expires'),
                             quote_name('cache_key')), [exp, key])
                    elif result and (mode == 'set' or
                                     (mode == 'add'
                                      and current_expires < now)):
                        cursor.execute(
                            'UPDATE %s SET %s = %%s, %s = %%s WHERE %s = %%s' %
                            (
                                table,
                                quote_name('value'),
                                quote_name('expires'),
                                quote_name('cache_key'),
                            ), [b64encoded, exp, key])
                    elif mode != 'touch':
                        cursor.execute(
                            'INSERT INTO %s (%s, %s, %s) VALUES (%%s, %%s, %%s)'
                            % (
                                table,
                                quote_name('cache_key'),
                                quote_name('value'),
                                quote_name('expires'),
                            ), [key, b64encoded, exp])
                    else:
                        return False  # touch failed.
            except DatabaseError:
                # To be threadsafe, updates/inserts are allowed to fail silently
                return False
            else:
                return True
Ejemplo n.º 9
0
    def __init__(self,
                 model,
                 data,
                 mapping,
                 layer=0,
                 source_srs=None,
                 encoding='utf-8',
                 transaction_mode='commit_on_success',
                 transform=True,
                 unique=None,
                 using=None):
        """
        A LayerMapping object is initialized using the given Model (not an instance),
        a DataSource (or string path to an OGR-supported data file), and a mapping
        dictionary.  See the module level docstring for more details and keyword
        argument usage.
        """
        # Getting the DataSource and the associated Layer.
        if isinstance(data, str):
            self.ds = DataSource(data, encoding=encoding)
        else:
            self.ds = data
        self.layer = self.ds[layer]

        self.using = using if using is not None else router.db_for_write(model)
        self.spatial_backend = connections[self.using].ops

        # Setting the mapping & model attributes.
        self.mapping = mapping
        self.model = model

        # Checking the layer -- initialization of the object will fail if
        # things don't check out before hand.
        self.check_layer()

        # Getting the geometry column associated with the model (an
        # exception will be raised if there is no geometry column).
        if connections[self.using].features.supports_transform:
            self.geo_field = self.geometry_field()
        else:
            transform = False

        # Checking the source spatial reference system, and getting
        # the coordinate transformation object (unless the `transform`
        # keyword is set to False)
        if transform:
            self.source_srs = self.check_srs(source_srs)
            self.transform = self.coord_transform()
        else:
            self.transform = transform

        # Setting the encoding for OFTString fields, if specified.
        if encoding:
            # Making sure the encoding exists, if not a LookupError
            # exception will be thrown.
            from codecs import lookup
            lookup(encoding)
            self.encoding = encoding
        else:
            self.encoding = None

        if unique:
            self.check_unique(unique)
            transaction_mode = 'autocommit'  # Has to be set to autocommit.
            self.unique = unique
        else:
            self.unique = None

        # Setting the transaction decorator with the function in the
        # transaction modes dictionary.
        self.transaction_mode = transaction_mode
        if transaction_mode == 'autocommit':
            self.transaction_decorator = None
        elif transaction_mode == 'commit_on_success':
            self.transaction_decorator = transaction.atomic
        else:
            raise LayerMapError('Unrecognized transaction mode: %s' %
                                transaction_mode)
Ejemplo n.º 10
0
 def test_select_for_update_on_multidb(self):
     query = Person.objects.select_for_update()
     self.assertEqual(router.db_for_write(Person), query.db)
Ejemplo n.º 11
0
 def update_or_create(self, **kwargs):
     kwargs[self.content_type_field_name] = self.content_type
     kwargs[self.object_id_field_name] = self.pk_val
     db = router.db_for_write(self.model, instance=self.instance)
     return super().using(db).update_or_create(**kwargs)
Ejemplo n.º 12
0
 def create(self, **kwargs):
     self._remove_prefetched_objects()
     kwargs[self.content_type_field_name] = self.content_type
     kwargs[self.object_id_field_name] = self.pk_val
     db = router.db_for_write(self.model, instance=self.instance)
     return super().using(db).create(**kwargs)