Fixed #10498 (again) -- Made sure the improvements done in r17641 have a smaller impact on speed. Thanks to Anssi Kääriäinen for the patch and Jonas Obrist for reviewing.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17698 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0ee801e360
commit
f7daa38a00
|
@ -20,7 +20,7 @@ from django.db.models.options import Options
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
from django.db.models.loading import register_models, get_model
|
from django.db.models.loading import register_models, get_model
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.functional import curry, Promise
|
from django.utils.functional import curry
|
||||||
from django.utils.encoding import smart_str, force_unicode
|
from django.utils.encoding import smart_str, force_unicode
|
||||||
from django.utils.text import get_text_list, capfirst
|
from django.utils.text import get_text_list, capfirst
|
||||||
|
|
||||||
|
@ -297,14 +297,10 @@ class Model(object):
|
||||||
# is *not* consumed. We rely on this, so don't change the order
|
# is *not* consumed. We rely on this, so don't change the order
|
||||||
# without changing the logic.
|
# without changing the logic.
|
||||||
for val, field in izip(args, fields_iter):
|
for val, field in izip(args, fields_iter):
|
||||||
if isinstance(val, Promise):
|
|
||||||
val = force_unicode(val)
|
|
||||||
setattr(self, field.attname, val)
|
setattr(self, field.attname, val)
|
||||||
else:
|
else:
|
||||||
# Slower, kwargs-ready version.
|
# Slower, kwargs-ready version.
|
||||||
for val, field in izip(args, fields_iter):
|
for val, field in izip(args, fields_iter):
|
||||||
if isinstance(val, Promise):
|
|
||||||
val = force_unicode(val)
|
|
||||||
setattr(self, field.attname, val)
|
setattr(self, field.attname, val)
|
||||||
kwargs.pop(field.name, None)
|
kwargs.pop(field.name, None)
|
||||||
# Maintain compatibility with existing calls.
|
# Maintain compatibility with existing calls.
|
||||||
|
@ -358,8 +354,6 @@ class Model(object):
|
||||||
# checked) by the RelatedObjectDescriptor.
|
# checked) by the RelatedObjectDescriptor.
|
||||||
setattr(self, field.name, rel_obj)
|
setattr(self, field.name, rel_obj)
|
||||||
else:
|
else:
|
||||||
if isinstance(val, Promise):
|
|
||||||
val = force_unicode(val)
|
|
||||||
setattr(self, field.attname, val)
|
setattr(self, field.attname, val)
|
||||||
|
|
||||||
if kwargs:
|
if kwargs:
|
||||||
|
|
|
@ -8,6 +8,8 @@ from django.db.models.sql.constants import *
|
||||||
from django.db.models.sql.datastructures import Date
|
from django.db.models.sql.datastructures import Date
|
||||||
from django.db.models.sql.query import Query
|
from django.db.models.sql.query import Query
|
||||||
from django.db.models.sql.where import AND, Constraint
|
from django.db.models.sql.where import AND, Constraint
|
||||||
|
from django.utils.functional import Promise
|
||||||
|
from django.utils.encoding import force_unicode
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery',
|
__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery',
|
||||||
|
@ -38,7 +40,7 @@ class DeleteQuery(Query):
|
||||||
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
||||||
where = self.where_class()
|
where = self.where_class()
|
||||||
where.add((Constraint(None, field.column, field), 'in',
|
where.add((Constraint(None, field.column, field), 'in',
|
||||||
pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), AND)
|
pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]), AND)
|
||||||
self.do_query(self.model._meta.db_table, where, using=using)
|
self.do_query(self.model._meta.db_table, where, using=using)
|
||||||
|
|
||||||
class UpdateQuery(Query):
|
class UpdateQuery(Query):
|
||||||
|
@ -67,14 +69,13 @@ class UpdateQuery(Query):
|
||||||
return super(UpdateQuery, self).clone(klass,
|
return super(UpdateQuery, self).clone(klass,
|
||||||
related_updates=self.related_updates.copy(), **kwargs)
|
related_updates=self.related_updates.copy(), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def update_batch(self, pk_list, values, using):
|
def update_batch(self, pk_list, values, using):
|
||||||
pk_field = self.model._meta.pk
|
pk_field = self.model._meta.pk
|
||||||
self.add_update_values(values)
|
self.add_update_values(values)
|
||||||
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
|
||||||
self.where = self.where_class()
|
self.where = self.where_class()
|
||||||
self.where.add((Constraint(None, pk_field.column, pk_field), 'in',
|
self.where.add((Constraint(None, pk_field.column, pk_field), 'in',
|
||||||
pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]),
|
pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]),
|
||||||
AND)
|
AND)
|
||||||
self.get_compiler(using).execute_sql(None)
|
self.get_compiler(using).execute_sql(None)
|
||||||
|
|
||||||
|
@ -101,6 +102,10 @@ class UpdateQuery(Query):
|
||||||
Used by add_update_values() as well as the "fast" update path when
|
Used by add_update_values() as well as the "fast" update path when
|
||||||
saving models.
|
saving models.
|
||||||
"""
|
"""
|
||||||
|
# Check that no Promise object passes to the query. Refs #10498.
|
||||||
|
values_seq = [(value[0], value[1], force_unicode(value[2]))
|
||||||
|
if isinstance(value[2], Promise) else value
|
||||||
|
for value in values_seq]
|
||||||
self.values.extend(values_seq)
|
self.values.extend(values_seq)
|
||||||
|
|
||||||
def add_related_update(self, model, field, value):
|
def add_related_update(self, model, field, value):
|
||||||
|
@ -159,6 +164,12 @@ class InsertQuery(Query):
|
||||||
into the query, for example.
|
into the query, for example.
|
||||||
"""
|
"""
|
||||||
self.fields = fields
|
self.fields = fields
|
||||||
|
# Check that no Promise object reaches the DB. Refs #10498.
|
||||||
|
for field in fields:
|
||||||
|
for obj in objs:
|
||||||
|
value = getattr(obj, field.attname)
|
||||||
|
if isinstance(value, Promise):
|
||||||
|
setattr(obj, field.attname, force_unicode(value))
|
||||||
self.objs = objs
|
self.objs = objs
|
||||||
self.raw = raw
|
self.raw = raw
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ from datetime import datetime
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db.models.fields import FieldDoesNotExist
|
from django.db.models.fields import FieldDoesNotExist
|
||||||
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
|
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
|
||||||
|
from django.utils.translation import ugettext_lazy
|
||||||
|
|
||||||
from .models import Article
|
from .models import Article
|
||||||
|
|
||||||
|
@ -553,3 +554,27 @@ class ModelTest(TestCase):
|
||||||
pub_date__year=2008).extra(
|
pub_date__year=2008).extra(
|
||||||
select={'dashed-value': '1', 'undashedvalue': '2'})
|
select={'dashed-value': '1', 'undashedvalue': '2'})
|
||||||
self.assertEqual(articles[0].undashedvalue, 2)
|
self.assertEqual(articles[0].undashedvalue, 2)
|
||||||
|
|
||||||
|
def test_create_relation_with_ugettext_lazy(self):
|
||||||
|
"""
|
||||||
|
Test that ugettext_lazy objects work when saving model instances
|
||||||
|
through various methods. Refs #10498.
|
||||||
|
"""
|
||||||
|
notlazy = u'test'
|
||||||
|
lazy = ugettext_lazy(notlazy)
|
||||||
|
reporter = Article.objects.create(headline=lazy, pub_date=datetime.now())
|
||||||
|
article = Article.objects.get()
|
||||||
|
self.assertEqual(article.headline, notlazy)
|
||||||
|
# test that assign + save works with Promise objecs
|
||||||
|
article.headline = lazy
|
||||||
|
article.save()
|
||||||
|
self.assertEqual(article.headline, notlazy)
|
||||||
|
# test .update()
|
||||||
|
Article.objects.update(headline=lazy)
|
||||||
|
article = Article.objects.get()
|
||||||
|
self.assertEqual(article.headline, notlazy)
|
||||||
|
# still test bulk_create()
|
||||||
|
Article.objects.all().delete()
|
||||||
|
Article.objects.bulk_create([Article(headline=lazy, pub_date=datetime.now())])
|
||||||
|
article = Article.objects.get()
|
||||||
|
self.assertEqual(article.headline, notlazy)
|
||||||
|
|
Loading…
Reference in New Issue