Commit acd1d439 authored by Loic Bistuer's avatar Loic Bistuer Committed by Tim Graham
Browse files

Fixed #20826 -- Moved Manager.raw() and Manager._insert() to the QuerySet class.

parent a3a59a31
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ import copy
import inspect

from django.db import router
from django.db.models.query import QuerySet, insert_query, RawQuerySet
from django.db.models.query import QuerySet
from django.db.models import signals
from django.db.models.fields import FieldDoesNotExist
from django.utils import six
@@ -169,12 +169,6 @@ class BaseManager(six.with_metaclass(RenameManagerMethods)):
        # understanding of how this comes into play.
        return self.get_queryset()

    def _insert(self, objs, fields, **kwargs):
        return insert_query(self.model, objs, fields, **kwargs)

    def raw(self, raw_query, params=None, *args, **kwargs):
        return RawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self._db, *args, **kwargs)

Manager = BaseManager.from_queryset(QuerySet, class_name='Manager')


+24 −13
Original line number Diff line number Diff line
@@ -413,8 +413,8 @@ class QuerySet(object):
        specifying whether an object was created.
        """
        lookup, params, _ = self._extract_model_params(defaults, **kwargs)
        try:
        self._for_write = True
        try:
            return self.get(**lookup), False
        except self.model.DoesNotExist:
            return self._create_object_from_params(lookup, params)
@@ -427,8 +427,8 @@ class QuerySet(object):
        specifying whether an object was created.
        """
        lookup, params, filtered_defaults = self._extract_model_params(defaults, **kwargs)
        try:
        self._for_write = True
        try:
            obj = self.get(**lookup)
        except self.model.DoesNotExist:
            obj, created = self._create_object_from_params(lookup, params)
@@ -623,6 +623,13 @@ class QuerySet(object):
    # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
    ##################################################

    def raw(self, raw_query, params=None, translations=None, using=None):
        if using is None:
            using = self.db
        return RawQuerySet(raw_query, model=self.model,
                params=params, translations=translations,
                using=using)

    def values(self, *fields):
        return self._clone(klass=ValuesQuerySet, setup=True, _fields=fields)

@@ -909,6 +916,21 @@ class QuerySet(object):
    ###################
    # PRIVATE METHODS #
    ###################

    def _insert(self, objs, fields, return_id=False, raw=False, using=None):
        """
        Inserts a new record for the given model. This provides an interface to
        the InsertQuery class and is how Model.save() is implemented.
        """
        self._for_write = True
        if using is None:
            using = self.db
        query = sql.InsertQuery(self.model)
        query.insert_values(fields, objs, raw=raw)
        return query.get_compiler(using=using).execute_sql(return_id)
    _insert.alters_data = True
    _insert.queryset_only = False

    def _batched_insert(self, objs, fields, batch_size):
        """
        A little helper method for bulk_insert to insert the bulk one batch
@@ -1601,17 +1623,6 @@ class RawQuerySet(object):
        return self._model_fields


def insert_query(model, objs, fields, return_id=False, raw=False, using=None):
    """
    Inserts a new record for the given model. This provides an interface to
    the InsertQuery class and is how Model.save() is implemented. It is not
    part of the public API.
    """
    query = sql.InsertQuery(model)
    query.insert_values(fields, objs, raw=raw)
    return query.get_compiler(using=using).execute_sql(return_id)


def prefetch_related_objects(result_cache, related_lookups):
    """
    Helper function for prefetch_related functionality
+22 −0
Original line number Diff line number Diff line
@@ -1262,6 +1262,28 @@ unexpectedly blocking.
Using ``select_for_update`` on backends which do not support
``SELECT ... FOR UPDATE`` (such as SQLite) will have no effect.

raw
~~~

.. method:: raw(raw_query, params=None, translations=None)

.. versionchanged:: 1.7

    ``raw`` was moved to the ``QuerySet`` class. It was previously only on
    :class:`~django.db.models.Manager`.

Takes a raw SQL query, executes it, and returns a
``django.db.models.query.RawQuerySet`` instance. This ``RawQuerySet`` instance
can be iterated over just like an normal QuerySet to provide object instances.

See the :ref:`executing-raw-queries` for more information.

.. warning::

  ``raw()`` always triggers a new query and doesn't account for previous
  filtering. As such, it should generally be called from the ``Manager`` or
  from a fresh ``QuerySet`` instance.

Methods that do not return QuerySets
------------------------------------

+2 −0
Original line number Diff line number Diff line
@@ -773,7 +773,9 @@ class ManagerTest(TestCase):
        'only',
        'using',
        'exists',
        '_insert',
        '_update',
        'raw',
    ]

    def test_manager_methods(self):