Skip to content

Commit

Permalink
Fixed #20826 -- Moved Manager.raw() and Manager._insert() to the Quer…
Browse files Browse the repository at this point in the history
…ySet class.
  • Loading branch information
loic authored and timgraham committed Jul 31, 2013
1 parent a3a59a3 commit acd1d43
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 20 deletions.
8 changes: 1 addition & 7 deletions django/db/models/manager.py
Expand Up @@ -2,7 +2,7 @@
import inspect import inspect


from django.db import router 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 import signals
from django.db.models.fields import FieldDoesNotExist from django.db.models.fields import FieldDoesNotExist
from django.utils import six from django.utils import six
Expand Down Expand Up @@ -169,12 +169,6 @@ def all(self):
# understanding of how this comes into play. # understanding of how this comes into play.
return self.get_queryset() 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') Manager = BaseManager.from_queryset(QuerySet, class_name='Manager')




Expand Down
37 changes: 24 additions & 13 deletions django/db/models/query.py
Expand Up @@ -413,8 +413,8 @@ def get_or_create(self, defaults=None, **kwargs):
specifying whether an object was created. specifying whether an object was created.
""" """
lookup, params, _ = self._extract_model_params(defaults, **kwargs) lookup, params, _ = self._extract_model_params(defaults, **kwargs)
self._for_write = True
try: try:
self._for_write = True
return self.get(**lookup), False return self.get(**lookup), False
except self.model.DoesNotExist: except self.model.DoesNotExist:
return self._create_object_from_params(lookup, params) return self._create_object_from_params(lookup, params)
Expand All @@ -427,8 +427,8 @@ def update_or_create(self, defaults=None, **kwargs):
specifying whether an object was created. specifying whether an object was created.
""" """
lookup, params, filtered_defaults = self._extract_model_params(defaults, **kwargs) lookup, params, filtered_defaults = self._extract_model_params(defaults, **kwargs)
self._for_write = True
try: try:
self._for_write = True
obj = self.get(**lookup) obj = self.get(**lookup)
except self.model.DoesNotExist: except self.model.DoesNotExist:
obj, created = self._create_object_from_params(lookup, params) obj, created = self._create_object_from_params(lookup, params)
Expand Down Expand Up @@ -623,6 +623,13 @@ def _prefetch_related_objects(self):
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # # 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): def values(self, *fields):
return self._clone(klass=ValuesQuerySet, setup=True, _fields=fields) return self._clone(klass=ValuesQuerySet, setup=True, _fields=fields)


Expand Down Expand Up @@ -909,6 +916,21 @@ def db(self):
################### ###################
# PRIVATE METHODS # # 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): def _batched_insert(self, objs, fields, batch_size):
""" """
A little helper method for bulk_insert to insert the bulk one batch A little helper method for bulk_insert to insert the bulk one batch
Expand Down Expand Up @@ -1601,17 +1623,6 @@ def model_fields(self):
return self._model_fields 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): def prefetch_related_objects(result_cache, related_lookups):
""" """
Helper function for prefetch_related functionality Helper function for prefetch_related functionality
Expand Down
22 changes: 22 additions & 0 deletions docs/ref/models/querysets.txt
Expand Up @@ -1262,6 +1262,28 @@ unexpectedly blocking.
Using ``select_for_update`` on backends which do not support Using ``select_for_update`` on backends which do not support
``SELECT ... FOR UPDATE`` (such as SQLite) will have no effect. ``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 Methods that do not return QuerySets
------------------------------------ ------------------------------------


Expand Down
2 changes: 2 additions & 0 deletions tests/basic/tests.py
Expand Up @@ -773,7 +773,9 @@ class ManagerTest(TestCase):
'only', 'only',
'using', 'using',
'exists', 'exists',
'_insert',
'_update', '_update',
'raw',
] ]


def test_manager_methods(self): def test_manager_methods(self):
Expand Down

0 comments on commit acd1d43

Please sign in to comment.