Author: Alex Date: 2009-06-06 13:01:43 -0500 (Sat, 06 Jun 2009) New Revision: 10933
Modified: django/branches/soc2009/multidb/django/contrib/admin/templates/admin/pagination.html django/branches/soc2009/multidb/django/db/models/query.py django/branches/soc2009/multidb/django/db/models/sql/query.py django/branches/soc2009/multidb/tests/modeltests/defer/models.py django/branches/soc2009/multidb/tests/regressiontests/defer_regress/models.py django/branches/soc2009/multidb/tests/regressiontests/queries/models.py Log: [soc2009/multidb] Merged up to trunk r10931. Resolved the slight merge conflict Modified: django/branches/soc2009/multidb/django/contrib/admin/templates/admin/pagination.html =================================================================== --- django/branches/soc2009/multidb/django/contrib/admin/templates/admin/pagination.html 2009-06-06 13:48:00 UTC (rev 10932) +++ django/branches/soc2009/multidb/django/contrib/admin/templates/admin/pagination.html 2009-06-06 18:01:43 UTC (rev 10933) @@ -8,5 +8,5 @@ {% endif %} {{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %} {% if show_all_url %} <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %} -{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="Save"/>{% endif %} +{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}"/>{% endif %} </p> Modified: django/branches/soc2009/multidb/django/db/models/query.py =================================================================== --- django/branches/soc2009/multidb/django/db/models/query.py 2009-06-06 13:48:00 UTC (rev 10932) +++ django/branches/soc2009/multidb/django/db/models/query.py 2009-06-06 18:01:43 UTC (rev 10933) @@ -7,6 +7,8 @@ except NameError: from sets import Set as set # Python 2.3 fallback +from copy import deepcopy + from django.db import connections, transaction, IntegrityError, DEFAULT_DB_ALIAS from django.db.models.aggregates import Aggregate from django.db.models.fields import DateField @@ -43,6 +45,17 @@ # PYTHON MAGIC METHODS # ######################## + def __deepcopy__(self, memo): + """ + Deep copy of a QuerySet doesn't populate the cache + """ + obj_dict = deepcopy(self.__dict__, memo) + obj_dict['_iter'] = None + + obj = self.__class__() + obj.__dict__.update(obj_dict) + return obj + def __getstate__(self): """ Allows the QuerySet to be pickled. @@ -193,7 +206,25 @@ index_start = len(extra_select) aggregate_start = index_start + len(self.model._meta.fields) - load_fields = only_load.get(self.model) + load_fields = [] + # If only/defer clauses have been specified, + # build the list of fields that are to be loaded. + if only_load: + for field, model in self.model._meta.get_fields_with_model(): + if model is None: + model = self.model + if field == self.model._meta.pk: + # Record the index of the primary key when it is found + pk_idx = len(load_fields) + try: + if field.name in only_load[model]: + # Add a field that has been explicitly included + load_fields.append(field.name) + except KeyError: + # Model wasn't explicitly listed in the only_load table + # Therefore, we need to load all fields from this model + load_fields.append(field.name) + skip = None if load_fields and not fill_cache: # Some fields have been deferred, so we have to initialise Modified: django/branches/soc2009/multidb/django/db/models/sql/query.py =================================================================== --- django/branches/soc2009/multidb/django/db/models/sql/query.py 2009-06-06 13:48:00 UTC (rev 10932) +++ django/branches/soc2009/multidb/django/db/models/sql/query.py 2009-06-06 18:01:43 UTC (rev 10933) @@ -635,10 +635,10 @@ # models. workset = {} for model, values in seen.iteritems(): - for field, f_model in model._meta.get_fields_with_model(): + for field in model._meta.local_fields: if field in values: continue - add_to_dict(workset, f_model or model, field) + add_to_dict(workset, model, field) for model, values in must_include.iteritems(): # If we haven't included a model in workset, we don't add the # corresponding must_include fields for that model, since an @@ -657,6 +657,12 @@ # included any fields, we have to make sure it's mentioned # so that only the "must include" fields are pulled in. seen[model] = values + # Now ensure that every model in the inheritance chain is mentioned + # in the parent list. Again, it must be mentioned to ensure that + # only "must include" fields are pulled in. + for model in orig_opts.get_parent_list(): + if model not in seen: + seen[model] = set() for model, values in seen.iteritems(): callback(target, model, values) @@ -1619,10 +1625,14 @@ entry.negate() self.where.add(entry, AND) break - elif not (lookup_type == 'in' and not value) and field.null: + elif not (lookup_type == 'in' + and not hasattr(value, 'as_sql') + and not hasattr(value, '_as_sql') + and not value) and field.null: # Leaky abstraction artifact: We have to specifically # exclude the "foo__in=[]" case from this handling, because # it's short-circuited in the Where class. + # We also need to handle the case where a subquery is provided entry = self.where_class() entry.add((Constraint(alias, col, None), 'isnull', True), AND) entry.negate() Modified: django/branches/soc2009/multidb/tests/modeltests/defer/models.py =================================================================== --- django/branches/soc2009/multidb/tests/modeltests/defer/models.py 2009-06-06 13:48:00 UTC (rev 10932) +++ django/branches/soc2009/multidb/tests/modeltests/defer/models.py 2009-06-06 18:01:43 UTC (rev 10933) @@ -17,6 +17,12 @@ def __unicode__(self): return self.name +class Child(Primary): + pass + +class BigChild(Primary): + other = models.CharField(max_length=50) + def count_delayed_fields(obj, debug=False): """ Returns the number of delayed attributes on the given model instance. @@ -33,7 +39,7 @@ __test__ = {"API_TEST": """ To all outward appearances, instances with deferred fields look the same as -normal instances when we examine attribut values. Therefore we test for the +normal instances when we examine attribute values. Therefore we test for the number of deferred fields on returned instances (by poking at the internals), as a way to observe what is going on. @@ -98,5 +104,89 @@ >>> Primary.objects.all() [<Primary: a new name>] +# Regression for #10572 - A subclass with no extra fields can defer fields from the base class +>>> _ = Child.objects.create(name="c1", value="foo", related=s1) +# You can defer a field on a baseclass when the subclass has no fields +>>> obj = Child.objects.defer("value").get(name="c1") +>>> count_delayed_fields(obj) +1 +>>> obj.name +u"c1" +>>> obj.value +u"foo" +>>> obj.name = "c2" +>>> obj.save() + +# You can retrive a single column on a base class with no fields +>>> obj = Child.objects.only("name").get(name="c2") +>>> count_delayed_fields(obj) +3 +>>> obj.name +u"c2" +>>> obj.value +u"foo" +>>> obj.name = "cc" +>>> obj.save() + +>>> _ = BigChild.objects.create(name="b1", value="foo", related=s1, other="bar") + +# You can defer a field on a baseclass +>>> obj = BigChild.objects.defer("value").get(name="b1") +>>> count_delayed_fields(obj) +1 +>>> obj.name +u"b1" +>>> obj.value +u"foo" +>>> obj.other +u"bar" +>>> obj.name = "b2" +>>> obj.save() + +# You can defer a field on a subclass +>>> obj = BigChild.objects.defer("other").get(name="b2") +>>> count_delayed_fields(obj) +1 +>>> obj.name +u"b2" +>>> obj.value +u"foo" +>>> obj.other +u"bar" +>>> obj.name = "b3" +>>> obj.save() + +# You can retrieve a single field on a baseclass +>>> obj = BigChild.objects.only("name").get(name="b3") +>>> count_delayed_fields(obj) +4 +>>> obj.name +u"b3" +>>> obj.value +u"foo" +>>> obj.other +u"bar" +>>> obj.name = "b4" +>>> obj.save() + +# You can retrieve a single field on a baseclass +>>> obj = BigChild.objects.only("other").get(name="b4") +>>> count_delayed_fields(obj) +4 +>>> obj.name +u"b4" +>>> obj.value +u"foo" +>>> obj.other +u"bar" +>>> obj.name = "bb" +>>> obj.save() + +# Finally, we need to flush the app cache for the defer module. +# Using only/defer creates some artifical entries in the app cache +# that messes up later tests. Purge all entries, just to be sure. +>>> from django.db.models.loading import cache +>>> cache.app_models['defer'] = {} + """} Modified: django/branches/soc2009/multidb/tests/regressiontests/defer_regress/models.py =================================================================== --- django/branches/soc2009/multidb/tests/regressiontests/defer_regress/models.py 2009-06-06 13:48:00 UTC (rev 10932) +++ django/branches/soc2009/multidb/tests/regressiontests/defer_regress/models.py 2009-06-06 18:01:43 UTC (rev 10933) @@ -84,7 +84,8 @@ (regression for #10710). >>> c1 = Child.objects.create(name="c1", value=42) ->>> obj = Leaf.objects.create(name="l1", child=c1) +>>> c2 = Child.objects.create(name="c2", value=37) +>>> obj = Leaf.objects.create(name="l1", child=c1, second_child=c2) >>> obj = Leaf.objects.only("name", "child").select_related()[0] >>> obj.child.name @@ -101,5 +102,24 @@ >>> c1 is c2 is c3 True +# Regression for #10733 - only() can be used on a model with two foreign keys. +>>> results = Leaf.objects.all().only('name', 'child', 'second_child').select_related() +>>> results[0].child.name +u'c1' +>>> results[0].second_child.name +u'c2' + +>>> results = Leaf.objects.all().only('name', 'child', 'second_child', 'child__name', 'second_child__name').select_related() +>>> results[0].child.name +u'c1' +>>> results[0].second_child.name +u'c2' + +# Finally, we need to flush the app cache for the defer module. +# Using only/defer creates some artifical entries in the app cache +# that messes up later tests. Purge all entries, just to be sure. +>>> from django.db.models.loading import cache +>>> cache.app_models['defer_regress'] = {} + """ } Modified: django/branches/soc2009/multidb/tests/regressiontests/queries/models.py =================================================================== --- django/branches/soc2009/multidb/tests/regressiontests/queries/models.py 2009-06-06 13:48:00 UTC (rev 10932) +++ django/branches/soc2009/multidb/tests/regressiontests/queries/models.py 2009-06-06 18:01:43 UTC (rev 10933) @@ -1143,6 +1143,33 @@ >>> r.save() >>> Ranking.objects.all() [<Ranking: 3: a1>, <Ranking: 2: a2>, <Ranking: 1: a3>] + +# Regression test for #10742: +# Queries used in an __in clause don't execute subqueries + +>>> subq = Author.objects.filter(num__lt=3000) +>>> qs = Author.objects.filter(pk__in=subq) +>>> list(qs) +[<Author: a1>, <Author: a2>] +# The subquery result cache should not be populated +>>> subq._result_cache is None +True + +>>> subq = Author.objects.filter(num__lt=3000) +>>> qs = Author.objects.exclude(pk__in=subq) +>>> list(qs) +[<Author: a3>, <Author: a4>] +# The subquery result cache should not be populated +>>> subq._result_cache is None +True + +>>> subq = Author.objects.filter(num__lt=3000) +>>> list(Author.objects.filter(Q(pk__in=subq) & Q(name='a1'))) +[<Author: a1>] +# The subquery result cache should not be populated +>>> subq._result_cache is None +True + """} # In Python 2.3 and the Python 2.6 beta releases, exceptions raised in __len__ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-updates?hl=en -~----------~----~----~----~------~----~------~--~---