Changeset 7500
- Timestamp:
- 04/28/08 09:43:46 (2 months ago)
- Files:
-
- django/branches/newforms-admin (modified) (1 prop)
- django/branches/newforms-admin/django/db/backends/__init__.py (modified) (1 diff)
- django/branches/newforms-admin/django/db/backends/mysql/base.py (modified) (1 diff)
- django/branches/newforms-admin/django/db/backends/mysql_old/base.py (modified) (1 diff)
- django/branches/newforms-admin/django/db/models/fields/__init__.py (modified) (2 diffs)
- django/branches/newforms-admin/django/db/models/query.py (modified) (3 diffs)
- django/branches/newforms-admin/django/db/models/sql/query.py (modified) (4 diffs)
- django/branches/newforms-admin/django/db/models/sql/subqueries.py (modified) (2 diffs)
- django/branches/newforms-admin/docs/db-api.txt (modified) (1 diff)
- django/branches/newforms-admin/tests/regressiontests/queries/models.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/newforms-admin
- Property svnmerge-integrated changed from /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7491 to /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7499
django/branches/newforms-admin/django/db/backends/__init__.py
r7479 r7500 52 52 uses_custom_query_class = False 53 53 empty_fetchmany_value = [] 54 update_can_self_select = True 54 55 55 56 class BaseDatabaseOperations(object): django/branches/newforms-admin/django/db/backends/mysql/base.py
r7479 r7500 64 64 inline_fk_references = False 65 65 empty_fetchmany_value = () 66 update_can_self_select = False 66 67 67 68 class DatabaseOperations(BaseDatabaseOperations): django/branches/newforms-admin/django/db/backends/mysql_old/base.py
r7479 r7500 68 68 inline_fk_references = False 69 69 empty_fetchmany_value = () 70 update_can_self_select = False 70 71 71 72 class DatabaseOperations(BaseDatabaseOperations): django/branches/newforms-admin/django/db/models/fields/__init__.py
r7479 r7500 10 10 from django.db import get_creation_module 11 11 from django.db.models import signals 12 from django.db.models.query_utils import QueryWrapper 12 13 from django.dispatch import dispatcher 13 14 from django.conf import settings … … 225 226 def get_db_prep_lookup(self, lookup_type, value): 226 227 "Returns field's value prepared for database lookup." 228 if hasattr(value, 'as_sql'): 229 sql, params = value.as_sql() 230 return QueryWrapper(('(%s)' % sql), params) 227 231 if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'): 228 232 return [value] django/branches/newforms-admin/django/db/models/query.py
r7492 r7500 29 29 ######################## 30 30 31 def __getstate__(self): 32 """ 33 Allows the Queryset to be pickled. 34 """ 35 # Force the cache to be fully populated. 36 len(self) 37 38 obj_dict = self.__dict__.copy() 39 obj_dict['_iter'] = None 40 return obj_dict 41 31 42 def __repr__(self): 32 43 return repr(list(self)) … … 38 49 if self._result_cache is None: 39 50 if self._iter: 40 self._result_cache = list(self._iter ())51 self._result_cache = list(self._iter) 41 52 else: 42 53 self._result_cache = list(self.iterator()) … … 498 509 # names of the model fields to select. 499 510 500 def __iter__(self):501 return self.iterator()502 503 511 def iterator(self): 504 512 self.query.trim_extra_select(self.extra_names) django/branches/newforms-admin/django/db/models/sql/query.py
r7479 r7500 99 99 memo[id(self)] = result 100 100 return result 101 102 def __getstate__(self): 103 """ 104 Pickling support. 105 """ 106 obj_dict = self.__dict__.copy() 107 del obj_dict['connection'] 108 return obj_dict 109 110 def __setstate__(self, obj_dict): 111 """ 112 Unpickling support. 113 """ 114 self.__dict__.update(obj_dict) 115 # XXX: Need a better solution for this when multi-db stuff is 116 # supported. It's the only class-reference to the module-level 117 # connection variable. 118 self.connection = connection 101 119 102 120 def get_meta(self): … … 896 914 (filter_string, value). E.g. ('name__contains', 'fred') 897 915 898 If 'negate' is True, this is an exclude() filter. If 'trim' is True, we 899 automatically trim the final join group (used internally when 900 constructing nested queries). 916 If 'negate' is True, this is an exclude() filter. It's important to 917 note that this method does not negate anything in the where-clause 918 object when inserting the filter constraints. This is because negated 919 filters often require multiple calls to add_filter() and the negation 920 should only happen once. So the caller is responsible for this (the 921 caller will normally be add_q(), so that as an example). 922 923 If 'trim' is True, we automatically trim the final join group (used 924 internally when constructing nested queries). 901 925 902 926 If 'can_reuse' is a set, we are processing a component of a … … 1002 1026 self.where.add((alias, col, field, lookup_type, value), connector) 1003 1027 if negate: 1004 self.where.negate()1005 1028 for alias in join_list: 1006 1029 self.promote_alias(alias) … … 1040 1063 self.add_q(child, used_aliases) 1041 1064 self.where.end_subtree() 1042 if q_object.negated:1043 self.where.children[-1].negate()1044 1065 else: 1045 1066 self.add_filter(child, connector, q_object.negated, 1046 1067 can_reuse=used_aliases) 1047 1068 connector = q_object.connector 1069 if q_object.negated: 1070 self.where.negate() 1048 1071 if subtree: 1049 1072 self.where.end_subtree() django/branches/newforms-admin/django/db/models/sql/subqueries.py
r7492 r7500 160 160 query = self.clone(klass=Query) 161 161 query.bump_prefix() 162 query.select = []163 162 query.extra_select = {} 164 query.add_fields([query.model._meta.pk.name]) 163 first_table = query.tables[0] 164 if query.alias_refcount[first_table] == 1: 165 # We can remove one table from the inner query. 166 query.unref_alias(first_table) 167 for i in xrange(1, len(query.tables)): 168 table = query.tables[i] 169 if query.alias_refcount[table]: 170 break 171 join_info = query.alias_map[table] 172 query.select = [(join_info[RHS_ALIAS], join_info[RHS_JOIN_COL])] 173 must_pre_select = False 174 else: 175 query.select = [] 176 query.add_fields([query.model._meta.pk.name]) 177 must_pre_select = not self.connection.features.update_can_self_select 165 178 166 179 # Now we adjust the current query: reset the where clause and get rid 167 180 # of all the tables we don't need (since they're in the sub-select). 168 181 self.where = self.where_class() 169 if self.related_updates: 182 if self.related_updates or must_pre_select: 183 # Either we're using the idents in multiple update queries (so 184 # don't want them to change), or the db backend doesn't support 185 # selecting from the updating table (e.g. MySQL). 170 186 idents = [] 171 187 for rows in query.execute_sql(MULTI): … … 174 190 self.related_ids = idents 175 191 else: 192 # The fast path. Filters and updates in one query. 176 193 self.add_filter(('pk__in', query)) 177 194 for alias in self.tables[1:]: django/branches/newforms-admin/docs/db-api.txt
r7492 r7500 376 376 iterating over a ``QuerySet`` will take advantage of your database to 377 377 load data and instantiate objects only as you need them. 378 379 380 Pickling QuerySets 381 ~~~~~~~~~~~~~~~~~~ 382 383 If you pickle_ a ``QuerySet``, this will also force all the results to be 384 loaded into memory prior to pickling. This is because pickling is usually used 385 as a precursor to caching and when the cached queryset is reloaded, you want 386 the results to already be present. This means that when you unpickle a 387 ``QuerySet``, it contains the results at the moment it was pickled, rather 388 than the results that are currently in the database. 389 390 If you only want to pickle the necessary information to recreate the 391 ``Queryset`` from the database at a later time, pickle the ``query`` attribute 392 of the ``QuerySet``. You can then recreate the original ``QuerySet`` (without 393 any results loaded) using some code like this:: 394 395 >>> import pickle 396 >>> query = pickle.loads(s) # Assuming 's' is the pickled string. 397 >>> qs = MyModel.objects.all() 398 >>> qs.query = query # Restore the original 'query'. 399 400 .. _pickle: http://docs.python.org/lib/module-pickle.html 378 401 379 402 Limiting QuerySets django/branches/newforms-admin/tests/regressiontests/queries/models.py
r7492 r7500 117 117 class Meta: 118 118 ordering = ['z'] 119 120 # A model and custom default manager combination. 121 class CustomManager(models.Manager): 122 def get_query_set(self): 123 return super(CustomManager, self).get_query_set().filter(public=True, 124 tag__name='t1') 125 126 class ManagedModel(models.Model): 127 data = models.CharField(max_length=10) 128 tag = models.ForeignKey(Tag) 129 public = models.BooleanField(default=True) 130 131 objects = CustomManager() 132 normal_manager = models.Manager() 133 134 def __unicode__(self): 135 return self.data 136 119 137 120 138 __test__ = {'API_TESTS':""" … … 659 677 >>> Item.objects.values('note__note').order_by('queries_note.note', 'id') 660 678 [{'note__note': u'n2'}, {'note__note': u'n3'}, {'note__note': u'n3'}, {'note__note': u'n3'}] 679 680 Bug #7096 -- Make sure exclude() with multiple conditions continues to work. 681 >>> Tag.objects.filter(parent=t1, name='t3').order_by('name') 682 [<Tag: t3>] 683 >>> Tag.objects.exclude(parent=t1, name='t3').order_by('name') 684 [<Tag: t1>, <Tag: t2>, <Tag: t4>, <Tag: t5>] 685 >>> Item.objects.exclude(tags__name='t1', name='one').order_by('name').distinct() 686 [<Item: four>, <Item: three>, <Item: two>] 687 >>> Item.objects.filter(name__in=['three', 'four']).exclude(tags__name='t1').order_by('name') 688 [<Item: four>, <Item: three>] 689 690 More twisted cases, involving nested negations. 691 >>> Item.objects.exclude(~Q(tags__name='t1', name='one')) 692 [<Item: one>] 693 >>> Item.objects.filter(~Q(tags__name='t1', name='one'), name='two') 694 [<Item: two>] 695 >>> Item.objects.exclude(~Q(tags__name='t1', name='one'), name='two') 696 [<Item: four>, <Item: one>, <Item: three>] 697 698 Bug #7095 699 Updates that are filtered on the model being updated are somewhat tricky to get 700 in MySQL. This exercises that case. 701 >>> mm = ManagedModel.objects.create(data='mm1', tag=t1, public=True) 702 >>> ManagedModel.objects.update(data='mm') 703 661 704 """} 662 705
