~canonical-django/canonical-django/project-template

« back to all changes in this revision

Viewing changes to trunk/python-packages/django/db/models/query.py

  • Committer: Matthew Nuzum
  • Date: 2008-11-13 05:46:03 UTC
  • Revision ID: matthew.nuzum@canonical.com-20081113054603-v0kvr6z6xyexvqt3
adding to version control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
try:
 
2
    set
 
3
except NameError:
 
4
    from sets import Set as set     # Python 2.3 fallback
 
5
 
 
6
from django.db import connection, transaction, IntegrityError
 
7
from django.db.models.fields import DateField
 
8
from django.db.models.query_utils import Q, select_related_descend
 
9
from django.db.models import signals, sql
 
10
from django.utils.datastructures import SortedDict
 
11
 
 
12
 
 
13
# Used to control how many objects are worked with at once in some cases (e.g.
 
14
# when deleting objects).
 
15
CHUNK_SIZE = 100
 
16
ITER_CHUNK_SIZE = CHUNK_SIZE
 
17
 
 
18
# Pull into this namespace for backwards compatibility.
 
19
EmptyResultSet = sql.EmptyResultSet
 
20
 
 
21
 
 
22
class CyclicDependency(Exception):
 
23
    """
 
24
    An error when dealing with a collection of objects that have a cyclic
 
25
    dependency, i.e. when deleting multiple objects.
 
26
    """
 
27
    pass
 
28
 
 
29
 
 
30
class CollectedObjects(object):
 
31
    """
 
32
    A container that stores keys and lists of values along with remembering the
 
33
    parent objects for all the keys.
 
34
 
 
35
    This is used for the database object deletion routines so that we can
 
36
    calculate the 'leaf' objects which should be deleted first.
 
37
    """
 
38
 
 
39
    def __init__(self):
 
40
        self.data = {}
 
41
        self.children = {}
 
42
 
 
43
    def add(self, model, pk, obj, parent_model, nullable=False):
 
44
        """
 
45
        Adds an item to the container.
 
46
 
 
47
        Arguments:
 
48
        * model - the class of the object being added.
 
49
        * pk - the primary key.
 
50
        * obj - the object itself.
 
51
        * parent_model - the model of the parent object that this object was
 
52
          reached through.
 
53
        * nullable - should be True if this relation is nullable.
 
54
 
 
55
        Returns True if the item already existed in the structure and
 
56
        False otherwise.
 
57
        """
 
58
        d = self.data.setdefault(model, SortedDict())
 
59
        retval = pk in d
 
60
        d[pk] = obj
 
61
        # Nullable relationships can be ignored -- they are nulled out before
 
62
        # deleting, and therefore do not affect the order in which objects
 
63
        # have to be deleted.
 
64
        if parent_model is not None and not nullable:
 
65
            self.children.setdefault(parent_model, []).append(model)
 
66
        return retval
 
67
 
 
68
    def __contains__(self, key):
 
69
        return self.data.__contains__(key)
 
70
 
 
71
    def __getitem__(self, key):
 
72
        return self.data[key]
 
73
 
 
74
    def __nonzero__(self):
 
75
        return bool(self.data)
 
76
 
 
77
    def iteritems(self):
 
78
        for k in self.ordered_keys():
 
79
            yield k, self[k]
 
80
 
 
81
    def items(self):
 
82
        return list(self.iteritems())
 
83
 
 
84
    def keys(self):
 
85
        return self.ordered_keys()
 
86
 
 
87
    def ordered_keys(self):
 
88
        """
 
89
        Returns the models in the order that they should be dealt with (i.e.
 
90
        models with no dependencies first).
 
91
        """
 
92
        dealt_with = SortedDict()
 
93
        # Start with items that have no children
 
94
        models = self.data.keys()
 
95
        while len(dealt_with) < len(models):
 
96
            found = False
 
97
            for model in models:
 
98
                if model in dealt_with:
 
99
                    continue
 
100
                children = self.children.setdefault(model, [])
 
101
                if len([c for c in children if c not in dealt_with]) == 0:
 
102
                    dealt_with[model] = None
 
103
                    found = True
 
104
            if not found:
 
105
                raise CyclicDependency(
 
106
                    "There is a cyclic dependency of items to be processed.")
 
107
 
 
108
        return dealt_with.keys()
 
109
 
 
110
    def unordered_keys(self):
 
111
        """
 
112
        Fallback for the case where is a cyclic dependency but we don't  care.
 
113
        """
 
114
        return self.data.keys()
 
115
 
 
116
 
 
117
class QuerySet(object):
 
118
    """
 
119
    Represents a lazy database lookup for a set of objects.
 
120
    """
 
121
    def __init__(self, model=None, query=None):
 
122
        self.model = model
 
123
        self.query = query or sql.Query(self.model, connection)
 
124
        self._result_cache = None
 
125
        self._iter = None
 
126
        self._sticky_filter = False
 
127
 
 
128
    ########################
 
129
    # PYTHON MAGIC METHODS #
 
130
    ########################
 
131
 
 
132
    def __getstate__(self):
 
133
        """
 
134
        Allows the QuerySet to be pickled.
 
135
        """
 
136
        # Force the cache to be fully populated.
 
137
        len(self)
 
138
 
 
139
        obj_dict = self.__dict__.copy()
 
140
        obj_dict['_iter'] = None
 
141
        return obj_dict
 
142
 
 
143
    def __repr__(self):
 
144
        return repr(list(self))
 
145
 
 
146
    def __len__(self):
 
147
        # Since __len__ is called quite frequently (for example, as part of
 
148
        # list(qs), we make some effort here to be as efficient as possible
 
149
        # whilst not messing up any existing iterators against the QuerySet.
 
150
        if self._result_cache is None:
 
151
            if self._iter:
 
152
                self._result_cache = list(self._iter)
 
153
            else:
 
154
                self._result_cache = list(self.iterator())
 
155
        elif self._iter:
 
156
            self._result_cache.extend(list(self._iter))
 
157
        return len(self._result_cache)
 
158
 
 
159
    def __iter__(self):
 
160
        if self._result_cache is None:
 
161
            self._iter = self.iterator()
 
162
            self._result_cache = []
 
163
        if self._iter:
 
164
            return self._result_iter()
 
165
        # Python's list iterator is better than our version when we're just
 
166
        # iterating over the cache.
 
167
        return iter(self._result_cache)
 
168
 
 
169
    def _result_iter(self):
 
170
        pos = 0
 
171
        while 1:
 
172
            upper = len(self._result_cache)
 
173
            while pos < upper:
 
174
                yield self._result_cache[pos]
 
175
                pos = pos + 1
 
176
            if not self._iter:
 
177
                raise StopIteration
 
178
            if len(self._result_cache) <= pos:
 
179
                self._fill_cache()
 
180
 
 
181
    def __nonzero__(self):
 
182
        if self._result_cache is not None:
 
183
            return bool(self._result_cache)
 
184
        try:
 
185
            iter(self).next()
 
186
        except StopIteration:
 
187
            return False
 
188
        return True
 
189
 
 
190
    def __getitem__(self, k):
 
191
        """
 
192
        Retrieves an item or slice from the set of results.
 
193
        """
 
194
        if not isinstance(k, (slice, int, long)):
 
195
            raise TypeError
 
196
        assert ((not isinstance(k, slice) and (k >= 0))
 
197
                or (isinstance(k, slice) and (k.start is None or k.start >= 0)
 
198
                    and (k.stop is None or k.stop >= 0))), \
 
199
                "Negative indexing is not supported."
 
200
 
 
201
        if self._result_cache is not None:
 
202
            if self._iter is not None:
 
203
                # The result cache has only been partially populated, so we may
 
204
                # need to fill it out a bit more.
 
205
                if isinstance(k, slice):
 
206
                    if k.stop is not None:
 
207
                        # Some people insist on passing in strings here.
 
208
                        bound = int(k.stop)
 
209
                    else:
 
210
                        bound = None
 
211
                else:
 
212
                    bound = k + 1
 
213
                if len(self._result_cache) < bound:
 
214
                    self._fill_cache(bound - len(self._result_cache))
 
215
            return self._result_cache[k]
 
216
 
 
217
        if isinstance(k, slice):
 
218
            qs = self._clone()
 
219
            if k.start is not None:
 
220
                start = int(k.start)
 
221
            else:
 
222
                start = None
 
223
            if k.stop is not None:
 
224
                stop = int(k.stop)
 
225
            else:
 
226
                stop = None
 
227
            qs.query.set_limits(start, stop)
 
228
            return k.step and list(qs)[::k.step] or qs
 
229
        try:
 
230
            qs = self._clone()
 
231
            qs.query.set_limits(k, k + 1)
 
232
            return list(qs)[0]
 
233
        except self.model.DoesNotExist, e:
 
234
            raise IndexError, e.args
 
235
 
 
236
    def __and__(self, other):
 
237
        self._merge_sanity_check(other)
 
238
        if isinstance(other, EmptyQuerySet):
 
239
            return other._clone()
 
240
        combined = self._clone()
 
241
        combined.query.combine(other.query, sql.AND)
 
242
        return combined
 
243
 
 
244
    def __or__(self, other):
 
245
        self._merge_sanity_check(other)
 
246
        combined = self._clone()
 
247
        if isinstance(other, EmptyQuerySet):
 
248
            return combined
 
249
        combined.query.combine(other.query, sql.OR)
 
250
        return combined
 
251
 
 
252
    ####################################
 
253
    # METHODS THAT DO DATABASE QUERIES #
 
254
    ####################################
 
255
 
 
256
    def iterator(self):
 
257
        """
 
258
        An iterator over the results from applying this QuerySet to the
 
259
        database.
 
260
        """
 
261
        fill_cache = self.query.select_related
 
262
        if isinstance(fill_cache, dict):
 
263
            requested = fill_cache
 
264
        else:
 
265
            requested = None
 
266
        max_depth = self.query.max_depth
 
267
        extra_select = self.query.extra_select.keys()
 
268
        index_start = len(extra_select)
 
269
        for row in self.query.results_iter():
 
270
            if fill_cache:
 
271
                obj, _ = get_cached_row(self.model, row, index_start,
 
272
                        max_depth, requested=requested)
 
273
            else:
 
274
                obj = self.model(*row[index_start:])
 
275
            for i, k in enumerate(extra_select):
 
276
                setattr(obj, k, row[i])
 
277
            yield obj
 
278
 
 
279
    def count(self):
 
280
        """
 
281
        Performs a SELECT COUNT() and returns the number of records as an
 
282
        integer.
 
283
 
 
284
        If the QuerySet is already fully cached this simply returns the length
 
285
        of the cached results set to avoid multiple SELECT COUNT(*) calls.
 
286
        """
 
287
        if self._result_cache is not None and not self._iter:
 
288
            return len(self._result_cache)
 
289
 
 
290
        return self.query.get_count()
 
291
 
 
292
    def get(self, *args, **kwargs):
 
293
        """
 
294
        Performs the query and returns a single object matching the given
 
295
        keyword arguments.
 
296
        """
 
297
        clone = self.filter(*args, **kwargs)
 
298
        num = len(clone)
 
299
        if num == 1:
 
300
            return clone._result_cache[0]
 
301
        if not num:
 
302
            raise self.model.DoesNotExist("%s matching query does not exist."
 
303
                    % self.model._meta.object_name)
 
304
        raise self.model.MultipleObjectsReturned("get() returned more than one %s -- it returned %s! Lookup parameters were %s"
 
305
                % (self.model._meta.object_name, num, kwargs))
 
306
 
 
307
    def create(self, **kwargs):
 
308
        """
 
309
        Creates a new object with the given kwargs, saving it to the database
 
310
        and returning the created object.
 
311
        """
 
312
        obj = self.model(**kwargs)
 
313
        obj.save(force_insert=True)
 
314
        return obj
 
315
 
 
316
    def get_or_create(self, **kwargs):
 
317
        """
 
318
        Looks up an object with the given kwargs, creating one if necessary.
 
319
        Returns a tuple of (object, created), where created is a boolean
 
320
        specifying whether an object was created.
 
321
        """
 
322
        assert kwargs, \
 
323
                'get_or_create() must be passed at least one keyword argument'
 
324
        defaults = kwargs.pop('defaults', {})
 
325
        try:
 
326
            return self.get(**kwargs), False
 
327
        except self.model.DoesNotExist:
 
328
            try:
 
329
                params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
 
330
                params.update(defaults)
 
331
                obj = self.model(**params)
 
332
                sid = transaction.savepoint()
 
333
                obj.save(force_insert=True)
 
334
                transaction.savepoint_commit(sid)
 
335
                return obj, True
 
336
            except IntegrityError, e:
 
337
                transaction.savepoint_rollback(sid)
 
338
                try:
 
339
                    return self.get(**kwargs), False
 
340
                except self.model.DoesNotExist:
 
341
                    raise e
 
342
 
 
343
    def latest(self, field_name=None):
 
344
        """
 
345
        Returns the latest object, according to the model's 'get_latest_by'
 
346
        option or optional given field_name.
 
347
        """
 
348
        latest_by = field_name or self.model._meta.get_latest_by
 
349
        assert bool(latest_by), "latest() requires either a field_name parameter or 'get_latest_by' in the model"
 
350
        assert self.query.can_filter(), \
 
351
                "Cannot change a query once a slice has been taken."
 
352
        obj = self._clone()
 
353
        obj.query.set_limits(high=1)
 
354
        obj.query.add_ordering('-%s' % latest_by)
 
355
        return obj.get()
 
356
 
 
357
    def in_bulk(self, id_list):
 
358
        """
 
359
        Returns a dictionary mapping each of the given IDs to the object with
 
360
        that ID.
 
361
        """
 
362
        assert self.query.can_filter(), \
 
363
                "Cannot use 'limit' or 'offset' with in_bulk"
 
364
        assert isinstance(id_list, (tuple,  list)), \
 
365
                "in_bulk() must be provided with a list of IDs."
 
366
        if not id_list:
 
367
            return {}
 
368
        qs = self._clone()
 
369
        qs.query.add_filter(('pk__in', id_list))
 
370
        return dict([(obj._get_pk_val(), obj) for obj in qs.iterator()])
 
371
 
 
372
    def delete(self):
 
373
        """
 
374
        Deletes the records in the current QuerySet.
 
375
        """
 
376
        assert self.query.can_filter(), \
 
377
                "Cannot use 'limit' or 'offset' with delete."
 
378
 
 
379
        del_query = self._clone()
 
380
 
 
381
        # Disable non-supported fields.
 
382
        del_query.query.select_related = False
 
383
        del_query.query.clear_ordering()
 
384
 
 
385
        # Delete objects in chunks to prevent the list of related objects from
 
386
        # becoming too long.
 
387
        while 1:
 
388
            # Collect all the objects to be deleted in this chunk, and all the
 
389
            # objects that are related to the objects that are to be deleted.
 
390
            seen_objs = CollectedObjects()
 
391
            for object in del_query[:CHUNK_SIZE]:
 
392
                object._collect_sub_objects(seen_objs)
 
393
 
 
394
            if not seen_objs:
 
395
                break
 
396
            delete_objects(seen_objs)
 
397
 
 
398
        # Clear the result cache, in case this QuerySet gets reused.
 
399
        self._result_cache = None
 
400
    delete.alters_data = True
 
401
 
 
402
    def update(self, **kwargs):
 
403
        """
 
404
        Updates all elements in the current QuerySet, setting all the given
 
405
        fields to the appropriate values.
 
406
        """
 
407
        assert self.query.can_filter(), \
 
408
                "Cannot update a query once a slice has been taken."
 
409
        query = self.query.clone(sql.UpdateQuery)
 
410
        query.add_update_values(kwargs)
 
411
        rows = query.execute_sql(None)
 
412
        transaction.commit_unless_managed()
 
413
        self._result_cache = None
 
414
        return rows
 
415
    update.alters_data = True
 
416
 
 
417
    def _update(self, values):
 
418
        """
 
419
        A version of update that accepts field objects instead of field names.
 
420
        Used primarily for model saving and not intended for use by general
 
421
        code (it requires too much poking around at model internals to be
 
422
        useful at that level).
 
423
        """
 
424
        assert self.query.can_filter(), \
 
425
                "Cannot update a query once a slice has been taken."
 
426
        query = self.query.clone(sql.UpdateQuery)
 
427
        query.add_update_fields(values)
 
428
        self._result_cache = None
 
429
        return query.execute_sql(None)
 
430
    _update.alters_data = True
 
431
 
 
432
    ##################################################
 
433
    # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
 
434
    ##################################################
 
435
 
 
436
    def values(self, *fields):
 
437
        return self._clone(klass=ValuesQuerySet, setup=True, _fields=fields)
 
438
 
 
439
    def values_list(self, *fields, **kwargs):
 
440
        flat = kwargs.pop('flat', False)
 
441
        if kwargs:
 
442
            raise TypeError('Unexpected keyword arguments to values_list: %s'
 
443
                    % (kwargs.keys(),))
 
444
        if flat and len(fields) > 1:
 
445
            raise TypeError("'flat' is not valid when values_list is called with more than one field.")
 
446
        return self._clone(klass=ValuesListQuerySet, setup=True, flat=flat,
 
447
                _fields=fields)
 
448
 
 
449
    def dates(self, field_name, kind, order='ASC'):
 
450
        """
 
451
        Returns a list of datetime objects representing all available dates for
 
452
        the given field_name, scoped to 'kind'.
 
453
        """
 
454
        assert kind in ("month", "year", "day"), \
 
455
                "'kind' must be one of 'year', 'month' or 'day'."
 
456
        assert order in ('ASC', 'DESC'), \
 
457
                "'order' must be either 'ASC' or 'DESC'."
 
458
        return self._clone(klass=DateQuerySet, setup=True,
 
459
                _field_name=field_name, _kind=kind, _order=order)
 
460
 
 
461
    def none(self):
 
462
        """
 
463
        Returns an empty QuerySet.
 
464
        """
 
465
        return self._clone(klass=EmptyQuerySet)
 
466
 
 
467
    ##################################################################
 
468
    # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
 
469
    ##################################################################
 
470
 
 
471
    def all(self):
 
472
        """
 
473
        Returns a new QuerySet that is a copy of the current one. This allows a
 
474
        QuerySet to proxy for a model manager in some cases.
 
475
        """
 
476
        return self._clone()
 
477
 
 
478
    def filter(self, *args, **kwargs):
 
479
        """
 
480
        Returns a new QuerySet instance with the args ANDed to the existing
 
481
        set.
 
482
        """
 
483
        return self._filter_or_exclude(False, *args, **kwargs)
 
484
 
 
485
    def exclude(self, *args, **kwargs):
 
486
        """
 
487
        Returns a new QuerySet instance with NOT (args) ANDed to the existing
 
488
        set.
 
489
        """
 
490
        return self._filter_or_exclude(True, *args, **kwargs)
 
491
 
 
492
    def _filter_or_exclude(self, negate, *args, **kwargs):
 
493
        if args or kwargs:
 
494
            assert self.query.can_filter(), \
 
495
                    "Cannot filter a query once a slice has been taken."
 
496
 
 
497
        clone = self._clone()
 
498
        if negate:
 
499
            clone.query.add_q(~Q(*args, **kwargs))
 
500
        else:
 
501
            clone.query.add_q(Q(*args, **kwargs))
 
502
        return clone
 
503
 
 
504
    def complex_filter(self, filter_obj):
 
505
        """
 
506
        Returns a new QuerySet instance with filter_obj added to the filters.
 
507
 
 
508
        filter_obj can be a Q object (or anything with an add_to_query()
 
509
        method) or a dictionary of keyword lookup arguments.
 
510
 
 
511
        This exists to support framework features such as 'limit_choices_to',
 
512
        and usually it will be more natural to use other methods.
 
513
        """
 
514
        if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
 
515
            clone = self._clone()
 
516
            clone.query.add_q(filter_obj)
 
517
            return clone
 
518
        else:
 
519
            return self._filter_or_exclude(None, **filter_obj)
 
520
 
 
521
    def select_related(self, *fields, **kwargs):
 
522
        """
 
523
        Returns a new QuerySet instance that will select related objects.
 
524
 
 
525
        If fields are specified, they must be ForeignKey fields and only those
 
526
        related objects are included in the selection.
 
527
        """
 
528
        depth = kwargs.pop('depth', 0)
 
529
        if kwargs:
 
530
            raise TypeError('Unexpected keyword arguments to select_related: %s'
 
531
                    % (kwargs.keys(),))
 
532
        obj = self._clone()
 
533
        if fields:
 
534
            if depth:
 
535
                raise TypeError('Cannot pass both "depth" and fields to select_related()')
 
536
            obj.query.add_select_related(fields)
 
537
        else:
 
538
            obj.query.select_related = True
 
539
        if depth:
 
540
            obj.query.max_depth = depth
 
541
        return obj
 
542
 
 
543
    def dup_select_related(self, other):
 
544
        """
 
545
        Copies the related selection status from the QuerySet 'other' to the
 
546
        current QuerySet.
 
547
        """
 
548
        self.query.select_related = other.query.select_related
 
549
 
 
550
    def order_by(self, *field_names):
 
551
        """
 
552
        Returns a new QuerySet instance with the ordering changed.
 
553
        """
 
554
        assert self.query.can_filter(), \
 
555
                "Cannot reorder a query once a slice has been taken."
 
556
        obj = self._clone()
 
557
        obj.query.clear_ordering()
 
558
        obj.query.add_ordering(*field_names)
 
559
        return obj
 
560
 
 
561
    def distinct(self, true_or_false=True):
 
562
        """
 
563
        Returns a new QuerySet instance that will select only distinct results.
 
564
        """
 
565
        obj = self._clone()
 
566
        obj.query.distinct = true_or_false
 
567
        return obj
 
568
 
 
569
    def extra(self, select=None, where=None, params=None, tables=None,
 
570
              order_by=None, select_params=None):
 
571
        """
 
572
        Adds extra SQL fragments to the query.
 
573
        """
 
574
        assert self.query.can_filter(), \
 
575
                "Cannot change a query once a slice has been taken"
 
576
        clone = self._clone()
 
577
        clone.query.add_extra(select, select_params, where, params, tables, order_by)
 
578
        return clone
 
579
 
 
580
    def reverse(self):
 
581
        """
 
582
        Reverses the ordering of the QuerySet.
 
583
        """
 
584
        clone = self._clone()
 
585
        clone.query.standard_ordering = not clone.query.standard_ordering
 
586
        return clone
 
587
 
 
588
    ###################
 
589
    # PRIVATE METHODS #
 
590
    ###################
 
591
 
 
592
    def _clone(self, klass=None, setup=False, **kwargs):
 
593
        if klass is None:
 
594
            klass = self.__class__
 
595
        query = self.query.clone()
 
596
        if self._sticky_filter:
 
597
            query.filter_is_sticky = True
 
598
        c = klass(model=self.model, query=query)
 
599
        c.__dict__.update(kwargs)
 
600
        if setup and hasattr(c, '_setup_query'):
 
601
            c._setup_query()
 
602
        return c
 
603
 
 
604
    def _fill_cache(self, num=None):
 
605
        """
 
606
        Fills the result cache with 'num' more entries (or until the results
 
607
        iterator is exhausted).
 
608
        """
 
609
        if self._iter:
 
610
            try:
 
611
                for i in range(num or ITER_CHUNK_SIZE):
 
612
                    self._result_cache.append(self._iter.next())
 
613
            except StopIteration:
 
614
                self._iter = None
 
615
 
 
616
    def _next_is_sticky(self):
 
617
        """
 
618
        Indicates that the next filter call and the one following that should
 
619
        be treated as a single filter. This is only important when it comes to
 
620
        determining when to reuse tables for many-to-many filters. Required so
 
621
        that we can filter naturally on the results of related managers.
 
622
 
 
623
        This doesn't return a clone of the current QuerySet (it returns
 
624
        "self"). The method is only used internally and should be immediately
 
625
        followed by a filter() that does create a clone.
 
626
        """
 
627
        self._sticky_filter = True
 
628
        return self
 
629
 
 
630
    def _merge_sanity_check(self, other):
 
631
        """
 
632
        Checks that we are merging two comparable QuerySet classes. By default
 
633
        this does nothing, but see the ValuesQuerySet for an example of where
 
634
        it's useful.
 
635
        """
 
636
        pass
 
637
 
 
638
 
 
639
class ValuesQuerySet(QuerySet):
 
640
    def __init__(self, *args, **kwargs):
 
641
        super(ValuesQuerySet, self).__init__(*args, **kwargs)
 
642
        # select_related isn't supported in values(). (FIXME -#3358)
 
643
        self.query.select_related = False
 
644
 
 
645
        # QuerySet.clone() will also set up the _fields attribute with the
 
646
        # names of the model fields to select.
 
647
 
 
648
    def iterator(self):
 
649
        if (not self.extra_names and
 
650
            len(self.field_names) != len(self.model._meta.fields)):
 
651
            self.query.trim_extra_select(self.extra_names)
 
652
        names = self.query.extra_select.keys() + self.field_names
 
653
        for row in self.query.results_iter():
 
654
            yield dict(zip(names, row))
 
655
 
 
656
    def _setup_query(self):
 
657
        """
 
658
        Constructs the field_names list that the values query will be
 
659
        retrieving.
 
660
 
 
661
        Called by the _clone() method after initializing the rest of the
 
662
        instance.
 
663
        """
 
664
        self.extra_names = []
 
665
        if self._fields:
 
666
            if not self.query.extra_select:
 
667
                field_names = list(self._fields)
 
668
            else:
 
669
                field_names = []
 
670
                for f in self._fields:
 
671
                    if self.query.extra_select.has_key(f):
 
672
                        self.extra_names.append(f)
 
673
                    else:
 
674
                        field_names.append(f)
 
675
        else:
 
676
            # Default to all fields.
 
677
            field_names = [f.attname for f in self.model._meta.fields]
 
678
 
 
679
        self.query.add_fields(field_names, False)
 
680
        self.query.default_cols = False
 
681
        self.field_names = field_names
 
682
 
 
683
    def _clone(self, klass=None, setup=False, **kwargs):
 
684
        """
 
685
        Cloning a ValuesQuerySet preserves the current fields.
 
686
        """
 
687
        c = super(ValuesQuerySet, self)._clone(klass, **kwargs)
 
688
        c._fields = self._fields[:]
 
689
        c.field_names = self.field_names
 
690
        c.extra_names = self.extra_names
 
691
        if setup and hasattr(c, '_setup_query'):
 
692
            c._setup_query()
 
693
        return c
 
694
 
 
695
    def _merge_sanity_check(self, other):
 
696
        super(ValuesQuerySet, self)._merge_sanity_check(other)
 
697
        if (set(self.extra_names) != set(other.extra_names) or
 
698
                set(self.field_names) != set(other.field_names)):
 
699
            raise TypeError("Merging '%s' classes must involve the same values in each case."
 
700
                    % self.__class__.__name__)
 
701
 
 
702
 
 
703
class ValuesListQuerySet(ValuesQuerySet):
 
704
    def iterator(self):
 
705
        self.query.trim_extra_select(self.extra_names)
 
706
        if self.flat and len(self._fields) == 1:
 
707
            for row in self.query.results_iter():
 
708
                yield row[0]
 
709
        elif not self.query.extra_select:
 
710
            for row in self.query.results_iter():
 
711
                yield tuple(row)
 
712
        else:
 
713
            # When extra(select=...) is involved, the extra cols come are
 
714
            # always at the start of the row, so we need to reorder the fields
 
715
            # to match the order in self._fields.
 
716
            names = self.query.extra_select.keys() + self.field_names
 
717
            for row in self.query.results_iter():
 
718
                data = dict(zip(names, row))
 
719
                yield tuple([data[f] for f in self._fields])
 
720
 
 
721
    def _clone(self, *args, **kwargs):
 
722
        clone = super(ValuesListQuerySet, self)._clone(*args, **kwargs)
 
723
        clone.flat = self.flat
 
724
        return clone
 
725
 
 
726
 
 
727
class DateQuerySet(QuerySet):
 
728
    def iterator(self):
 
729
        return self.query.results_iter()
 
730
 
 
731
    def _setup_query(self):
 
732
        """
 
733
        Sets up any special features of the query attribute.
 
734
 
 
735
        Called by the _clone() method after initializing the rest of the
 
736
        instance.
 
737
        """
 
738
        self.query = self.query.clone(klass=sql.DateQuery, setup=True)
 
739
        self.query.select = []
 
740
        field = self.model._meta.get_field(self._field_name, many_to_many=False)
 
741
        assert isinstance(field, DateField), "%r isn't a DateField." \
 
742
                % field.name
 
743
        self.query.add_date_select(field, self._kind, self._order)
 
744
        if field.null:
 
745
            self.query.add_filter(('%s__isnull' % field.name, False))
 
746
 
 
747
    def _clone(self, klass=None, setup=False, **kwargs):
 
748
        c = super(DateQuerySet, self)._clone(klass, False, **kwargs)
 
749
        c._field_name = self._field_name
 
750
        c._kind = self._kind
 
751
        if setup and hasattr(c, '_setup_query'):
 
752
            c._setup_query()
 
753
        return c
 
754
 
 
755
 
 
756
class EmptyQuerySet(QuerySet):
 
757
    def __init__(self, model=None, query=None):
 
758
        super(EmptyQuerySet, self).__init__(model, query)
 
759
        self._result_cache = []
 
760
 
 
761
    def __and__(self, other):
 
762
        return self._clone()
 
763
 
 
764
    def __or__(self, other):
 
765
        return other._clone()
 
766
 
 
767
    def count(self):
 
768
        return 0
 
769
 
 
770
    def delete(self):
 
771
        pass
 
772
 
 
773
    def _clone(self, klass=None, setup=False, **kwargs):
 
774
        c = super(EmptyQuerySet, self)._clone(klass, **kwargs)
 
775
        c._result_cache = []
 
776
        return c
 
777
 
 
778
    def iterator(self):
 
779
        # This slightly odd construction is because we need an empty generator
 
780
        # (it raises StopIteration immediately).
 
781
        yield iter([]).next()
 
782
 
 
783
 
 
784
def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
 
785
                   requested=None):
 
786
    """
 
787
    Helper function that recursively returns an object with the specified
 
788
    related attributes already populated.
 
789
    """
 
790
    if max_depth and requested is None and cur_depth > max_depth:
 
791
        # We've recursed deeply enough; stop now.
 
792
        return None
 
793
 
 
794
    restricted = requested is not None
 
795
    index_end = index_start + len(klass._meta.fields)
 
796
    fields = row[index_start:index_end]
 
797
    if not [x for x in fields if x is not None]:
 
798
        # If we only have a list of Nones, there was not related object.
 
799
        obj = None
 
800
    else:
 
801
        obj = klass(*fields)
 
802
    for f in klass._meta.fields:
 
803
        if not select_related_descend(f, restricted, requested):
 
804
            continue
 
805
        if restricted:
 
806
            next = requested[f.name]
 
807
        else:
 
808
            next = None
 
809
        cached_row = get_cached_row(f.rel.to, row, index_end, max_depth,
 
810
                cur_depth+1, next)
 
811
        if cached_row:
 
812
            rel_obj, index_end = cached_row
 
813
            if obj is not None:
 
814
                setattr(obj, f.get_cache_name(), rel_obj)
 
815
    return obj, index_end
 
816
 
 
817
 
 
818
def delete_objects(seen_objs):
 
819
    """
 
820
    Iterate through a list of seen classes, and remove any instances that are
 
821
    referred to.
 
822
    """
 
823
    try:
 
824
        ordered_classes = seen_objs.keys()
 
825
    except CyclicDependency:
 
826
        # If there is a cyclic dependency, we cannot in general delete the
 
827
        # objects.  However, if an appropriate transaction is set up, or if the
 
828
        # database is lax enough, it will succeed. So for now, we go ahead and
 
829
        # try anyway.
 
830
        ordered_classes = seen_objs.unordered_keys()
 
831
 
 
832
    obj_pairs = {}
 
833
    for cls in ordered_classes:
 
834
        items = seen_objs[cls].items()
 
835
        items.sort()
 
836
        obj_pairs[cls] = items
 
837
 
 
838
        # Pre-notify all instances to be deleted.
 
839
        for pk_val, instance in items:
 
840
            signals.pre_delete.send(sender=cls, instance=instance)
 
841
 
 
842
        pk_list = [pk for pk,instance in items]
 
843
        del_query = sql.DeleteQuery(cls, connection)
 
844
        del_query.delete_batch_related(pk_list)
 
845
 
 
846
        update_query = sql.UpdateQuery(cls, connection)
 
847
        for field, model in cls._meta.get_fields_with_model():
 
848
            if (field.rel and field.null and field.rel.to in seen_objs and
 
849
                    filter(lambda f: f.column == field.column,
 
850
                    field.rel.to._meta.fields)):
 
851
                if model:
 
852
                    sql.UpdateQuery(model, connection).clear_related(field,
 
853
                            pk_list)
 
854
                else:
 
855
                    update_query.clear_related(field, pk_list)
 
856
 
 
857
    # Now delete the actual data.
 
858
    for cls in ordered_classes:
 
859
        items = obj_pairs[cls]
 
860
        items.reverse()
 
861
 
 
862
        pk_list = [pk for pk,instance in items]
 
863
        del_query = sql.DeleteQuery(cls, connection)
 
864
        del_query.delete_batch(pk_list)
 
865
 
 
866
        # Last cleanup; set NULLs where there once was a reference to the
 
867
        # object, NULL the primary key of the found objects, and perform
 
868
        # post-notification.
 
869
        for pk_val, instance in items:
 
870
            for field in cls._meta.fields:
 
871
                if field.rel and field.null and field.rel.to in seen_objs:
 
872
                    setattr(instance, field.attname, None)
 
873
 
 
874
            signals.post_delete.send(sender=cls, instance=instance)
 
875
            setattr(instance, cls._meta.pk.attname, None)
 
876
 
 
877
    transaction.commit_unless_managed()
 
878
 
 
879
 
 
880
def insert_query(model, values, return_id=False, raw_values=False):
 
881
    """
 
882
    Inserts a new record for the given model. This provides an interface to
 
883
    the InsertQuery class and is how Model.save() is implemented. It is not
 
884
    part of the public API.
 
885
    """
 
886
    query = sql.InsertQuery(model, connection)
 
887
    query.insert_values(values, raw_values)
 
888
    return query.execute_sql(return_id)