Commit b79702b2 authored by Jacob Kaplan-Moss's avatar Jacob Kaplan-Moss
Browse files

Fixed #11402: added a `QuerySet.exists()` method. Thanks, Alex Gaynor.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11646 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 9f70783b
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -3,11 +3,6 @@ import types
import sys
import os
from itertools import izip
try:
    set
except NameError:
    from sets import Set as set     # Python 2.3 fallback.

import django.db.models.manager     # Imported to register signal handler.
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
from django.db.models.fields import AutoField, FieldDoesNotExist
@@ -22,7 +17,6 @@ from django.utils.functional import curry
from django.utils.encoding import smart_str, force_unicode, smart_unicode
from django.conf import settings


class ModelBase(type):
    """
    Metaclass for all models.
@@ -236,7 +230,6 @@ class ModelBase(type):

        signals.class_prepared.send(sender=cls)


class Model(object):
    __metaclass__ = ModelBase
    _deferred = False
@@ -467,7 +460,7 @@ class Model(object):
            if pk_set:
                # Determine whether a record with the primary key already exists.
                if (force_update or (not force_insert and
                        manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by())):
                        manager.filter(pk=pk_val).exists())):
                    # It does already exist, so do an UPDATE.
                    if force_update or non_pks:
                        values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
+3 −1
Original line number Diff line number Diff line
import copy

from django.db.models.query import QuerySet, EmptyQuerySet, insert_query
from django.db.models import signals
from django.db.models.fields import FieldDoesNotExist
@@ -173,6 +172,9 @@ class Manager(object):
    def only(self, *args, **kwargs):
        return self.get_query_set().only(*args, **kwargs)

    def exists(self, *args, **kwargs):
        return self.get_query_ste().exists(*args, **kwargs)

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

+5 −7
Original line number Diff line number Diff line
@@ -2,20 +2,13 @@
The main QuerySet implementation. This provides the public API for the ORM.
"""

try:
    set
except NameError:
    from sets import Set as set     # Python 2.3 fallback

from copy import deepcopy

from django.db import connection, transaction, IntegrityError
from django.db.models.aggregates import Aggregate
from django.db.models.fields import DateField
from django.db.models.query_utils import Q, select_related_descend, CollectedObjects, CyclicDependency, deferred_class_factory
from django.db.models import signals, sql


# Used to control how many objects are worked with at once in some cases (e.g.
# when deleting objects).
CHUNK_SIZE = 100
@@ -444,6 +437,11 @@ class QuerySet(object):
        return query.execute_sql(None)
    _update.alters_data = True

    def exists(self):
        if self._result_cache is None:
            return self.query.has_results()
        return bool(self._result_cache)

    ##################################################
    # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
    ##################################################
+9 −6
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@ all about the internals of models in order to get the information it needs.
"""

from copy import deepcopy

from django.utils.tree import Node
from django.utils.datastructures import SortedDict
from django.utils.encoding import force_unicode
@@ -24,11 +23,6 @@ from django.core.exceptions import FieldError
from datastructures import EmptyResultSet, Empty, MultiJoin
from constants import *

try:
    set
except NameError:
    from sets import Set as set     # Python 2.3 fallback

__all__ = ['Query', 'BaseQuery']

class BaseQuery(object):
@@ -384,6 +378,15 @@ class BaseQuery(object):

        return number

    def has_results(self):
        q = self.clone()
        q.add_extra({'a': 1}, None, None, None, None, None)
        q.add_fields(())
        q.set_extra_mask(('a',))
        q.set_aggregate_mask(())
        q.clear_ordering()
        return bool(q.execute_sql())

    def as_sql(self, with_limits=True, with_col_aliases=False):
        """
        Creates the SQL for this query. Returns the SQL string and list of
+2 −6
Original line number Diff line number Diff line
@@ -319,9 +319,7 @@ class BaseModelForm(BaseForm):
            if self.instance.pk is not None:
                qs = qs.exclude(pk=self.instance.pk)

            # This cute trick with extra/values is the most efficient way to
            # tell if a particular query returns any results.
            if qs.extra(select={'a': 1}).values('a').order_by():
            if qs.exists():
                if len(unique_check) == 1:
                    self._errors[unique_check[0]] = ErrorList([self.unique_error_message(unique_check)])
                else:
@@ -354,9 +352,7 @@ class BaseModelForm(BaseForm):
            if self.instance.pk is not None:
                qs = qs.exclude(pk=self.instance.pk)

            # This cute trick with extra/values is the most efficient way to
            # tell if a particular query returns any results.
            if qs.extra(select={'a': 1}).values('a').order_by():
            if qs.exists():
                self._errors[field] = ErrorList([
                    self.date_error_message(lookup_type, field, unique_for)
                ])
Loading