diff --git a/django_mongodb/manager.py b/django_mongodb/manager.py new file mode 100644 index 000000000..d3481b3b5 --- /dev/null +++ b/django_mongodb/manager.py @@ -0,0 +1,8 @@ +from django.db.models.manager import BaseManager +from .query import MongoQuerySet + + +class MongoManager(BaseManager.from_queryset(MongoQuerySet)): + pass + # def get_queryset(self): + # return MongoQuerySet(self.model, using=self._db) diff --git a/django_mongodb/query.py b/django_mongodb/query.py index 049775205..ca6d2ee36 100644 --- a/django_mongodb/query.py +++ b/django_mongodb/query.py @@ -1,14 +1,19 @@ from functools import reduce, wraps from operator import add as add_operator +from collections.abc import Mapping from django.core.exceptions import EmptyResultSet, FullResultSet -from django.db import DatabaseError, IntegrityError, NotSupportedError +from django.db import DatabaseError, IntegrityError, NotSupportedError, connections +from django.db.models import QuerySet from django.db.models.expressions import Case, Col, When from django.db.models.functions import Mod from django.db.models.lookups import Exact -from django.db.models.sql.constants import INNER +from django.db.models.query import BaseIterable, RawQuerySet +from django.db.models.sql.constants import INNER, GET_ITERATOR_CHUNK_SIZE from django.db.models.sql.datastructures import Join from django.db.models.sql.where import AND, OR, XOR, ExtraWhere, NothingNode, WhereNode +from django.db.models.sql import Query, RawQuery +from django.utils.functional import cached_property from pymongo.errors import BulkWriteError, DuplicateKeyError, PyMongoError @@ -302,3 +307,63 @@ def register_nodes(): Join.as_mql = join NothingNode.as_mql = NothingNode.as_sql WhereNode.as_mql = where_node + + +class MongoQuerySet(QuerySet): + def raw_mql(self, raw_query, params=(), translations=None, using=None): + return MongoRawQuerySet( + raw_query, + model=self.model, + params=params, + translations=translations, + using=using, + ) + +class MongoRawQuery(RawQuery): + def _execute_query(self): + connection = connections[self.using] + + # Adapt parameters to the database, as much as possible considering + # that the target type isn't known. See #17755. + params_type = self.params_type + adapter = connection.ops.adapt_unknown_value + if params_type is tuple: + params = tuple(adapter(val) for val in self.params) + elif params_type is dict: + params = {key: adapter(val) for key, val in self.params.items()} + elif params_type is None: + params = None + else: + raise RuntimeError("Unexpected params type: %s" % params_type) + + self.cursor = connection.cursor() + self.cursor.execute(self.sql, params) + + +class MongoRawQuerySet(RawQuerySet): + """ + Provide an iterator which converts the results of raw SQL queries into + annotated model instances. + """ + + def __init__( + self, + raw_query, + model=None, + query=None, + params=(), + translations=None, + using=None, + hints=None, + ): + self.model = model + self._db = using + self._hints = hints or {} + self.query = query or MongoRawQuery(sql=raw_query, using=self.db, params=params) + # self.params = params + # self.translations = translations or {} + self._result_cache = None + # self._prefetch_related_lookups = () + # self._prefetch_done = False + +