From 13ae9e484d6dbd1ab0affee07922a5337591fa5f Mon Sep 17 00:00:00 2001 From: Brian Rosner Date: Wed, 14 May 2008 05:48:44 +0000 Subject: [PATCH] newforms-admin: Merged from trunk up to [7526]. git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7533 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/backends/oracle/query.py | 8 +++---- django/db/models/base.py | 28 ++----------------------- django/db/models/query.py | 4 ++-- django/db/models/sql/query.py | 3 ++- django/db/models/sql/where.py | 6 +++--- docs/request_response.txt | 23 +++++++++++++++++++- tests/modeltests/basic/models.py | 12 +++++++++++ tests/regressiontests/queries/models.py | 8 +++---- 8 files changed, 51 insertions(+), 41 deletions(-) diff --git a/django/db/backends/oracle/query.py b/django/db/backends/oracle/query.py index 033ffe8533..7e50c7b5db 100644 --- a/django/db/backends/oracle/query.py +++ b/django/db/backends/oracle/query.py @@ -1,6 +1,6 @@ """ -Custom Query class for this backend (a derivative of -django.db.models.sql.query.Query). +Custom Query class for Oracle. +Derives from: django.db.models.sql.query.Query """ import datetime @@ -12,8 +12,8 @@ _classes = {} def query_class(QueryClass, Database): """ - Returns a custom djang.db.models.sql.query.Query subclass that is - appropraite for Oracle. + Returns a custom django.db.models.sql.query.Query subclass that is + appropriate for Oracle. The 'Database' module (cx_Oracle) is passed in here so that all the setup required to import it only needs to be done by the calling module. diff --git a/django/db/models/base.py b/django/db/models/base.py index e1f846034c..01c2f31794 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -234,32 +234,6 @@ class Model(object): raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0] dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self) - def from_sequence(cls, values): - """ - An alternate class constructor, primarily for internal use. - - Creates a model instance from a sequence of values (which corresponds - to all the non-many-to-many fields in creation order. If there are more - fields than values, the remaining (final) fields are given their - default values. - - ForeignKey fields can only be initialised using id values, not - instances, in this method. - """ - dispatcher.send(signal=signals.pre_init, sender=cls, args=values, - kwargs={}) - obj = Empty() - obj.__class__ = cls - field_iter = iter(obj._meta.fields) - for val, field in izip(values, field_iter): - setattr(obj, field.attname, val) - for field in field_iter: - setattr(obj, field.attname, field.get_default()) - dispatcher.send(signal=signals.post_init, sender=cls, instance=obj) - return obj - - from_sequence = classmethod(from_sequence) - def __repr__(self): return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self))) @@ -362,6 +336,8 @@ class Model(object): dispatcher.send(signal=signals.post_save, sender=self.__class__, instance=self, created=(not record_exists), raw=raw) + save_base.alters_data = True + def validate(self): """ First coerces all fields on this instance to their proper Python types. diff --git a/django/db/models/query.py b/django/db/models/query.py index 65048c7ba8..6b341ba9ab 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -164,7 +164,7 @@ class QuerySet(object): obj, _ = get_cached_row(self.model, row, index_start, max_depth, requested=requested) else: - obj = self.model.from_sequence(row[index_start:]) + obj = self.model(*row[index_start:]) for i, k in enumerate(extra_select): setattr(obj, k, row[i]) yield obj @@ -655,7 +655,7 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0, restricted = requested is not None index_end = index_start + len(klass._meta.fields) - obj = klass.from_sequence(row[index_start:index_end]) + obj = klass(*row[index_start:index_end]) for f in klass._meta.fields: if (not f.rel or (not restricted and f.null) or (restricted and f.name not in requested) or f.rel.parent_link): diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 7e9fb00418..a6957bab7b 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -394,7 +394,8 @@ class Query(object): some cases to avoid ambiguitity with nested queries. """ qn = self.quote_name_unless_alias - result = ['(%s) AS %s' % (col, alias) for alias, col in self.extra_select.iteritems()] + qn2 = self.connection.ops.quote_name + result = ['(%s) AS %s' % (col, qn2(alias)) for alias, col in self.extra_select.iteritems()] aliases = set(self.extra_select.keys()) if with_aliases: col_aliases = aliases.copy() diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index c8857a01fe..3e8bfed087 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -51,12 +51,12 @@ class WhereNode(tree.Node): format = '(%s)' elif isinstance(child, tree.Node): sql, params = self.as_sql(child, qn) - if len(child.children) == 1: + if child.negated: + format = 'NOT (%s)' + elif len(child.children) == 1: format = '%s' else: format = '(%s)' - if child.negated: - format = 'NOT %s' % format else: sql, params = self.make_atom(child, qn) format = '%s' diff --git a/docs/request_response.txt b/docs/request_response.txt index a4f03b9185..866a697e31 100644 --- a/docs/request_response.txt +++ b/docs/request_response.txt @@ -402,6 +402,27 @@ hard-coded strings. If you use this technique, follow these guidelines: content, you can't use the ``HttpResponse`` instance as a file-like object. Doing so will raise ``Exception``. +Setting headers +~~~~~~~~~~~~~~~ + +To set a header in your response, just treat it like a dictionary:: + + >>> response = HttpResponse() + >>> response['Pragma'] = 'no-cache' + +Telling the browser to treat the response as a file attachment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To tell the browser to treat the response as a file attachment, use the +``mimetype`` argument and set the ``Content-Disposition`` header. For example, +this is how you might return a Microsoft Excel spreadsheet:: + + >>> response = HttpResponse(my_data, mimetype='application/vnd.ms-excel') + >>> response['Content-Disposition'] = 'attachment; filename=foo.xls' + +There's nothing Django-specific about the ``Content-Disposition`` header, but +it's easy to forget the syntax, so we've included it here. + Methods ------- @@ -420,7 +441,7 @@ Methods but since this is actually the value included in the HTTP ``Content-Type`` header, it can also include the character set encoding, which makes it more than just a MIME type specification. If ``mimetype`` is specified - (not None), that value is used. Otherwise, ``content_type`` is used. If + (not ``None``), that value is used. Otherwise, ``content_type`` is used. If neither is given, the ``DEFAULT_CONTENT_TYPE`` setting is used. ``__setitem__(header, value)`` diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py index 51de8a50f8..d7c27cb15b 100644 --- a/tests/modeltests/basic/models.py +++ b/tests/modeltests/basic/models.py @@ -398,4 +398,16 @@ u'\u6797\u539f \u3081\u3050\u307f' >>> s = set([a10, a11, a12]) >>> Article.objects.get(headline='Article 11') in s True + +# The 'select' argument to extra() supports names with dashes in them, as long +# as you use values(). +>>> Article.objects.filter(pub_date__year=2008).extra(select={'dashed-value': '1'}).values('headline', 'dashed-value') +[{'headline': u'Article 11', 'dashed-value': 1}, {'headline': u'Article 12', 'dashed-value': 1}] + +# If you use 'select' with extra() and names containing dashes on a query +# that's *not* a values() query, those extra 'select' values will silently be +# ignored. +>>> articles = Article.objects.filter(pub_date__year=2008).extra(select={'dashed-value': '1', 'undashedvalue': '2'}) +>>> articles[0].undashedvalue +2 """ diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py index 6fd361ec19..5beaf5fb09 100644 --- a/tests/regressiontests/queries/models.py +++ b/tests/regressiontests/queries/models.py @@ -120,13 +120,13 @@ class LoopZ(models.Model): # A model and custom default manager combination. class CustomManager(models.Manager): def get_query_set(self): - return super(CustomManager, self).get_query_set().filter(public=True, - tag__name='t1') + qs = super(CustomManager, self).get_query_set() + return qs.filter(is_public=True, tag__name='t1') class ManagedModel(models.Model): data = models.CharField(max_length=10) tag = models.ForeignKey(Tag) - public = models.BooleanField(default=True) + is_public = models.BooleanField(default=True) objects = CustomManager() normal_manager = models.Manager() @@ -698,7 +698,7 @@ More twisted cases, involving nested negations. Bug #7095 Updates that are filtered on the model being updated are somewhat tricky to get in MySQL. This exercises that case. ->>> mm = ManagedModel.objects.create(data='mm1', tag=t1, public=True) +>>> mm = ManagedModel.objects.create(data='mm1', tag=t1, is_public=True) >>> ManagedModel.objects.update(data='mm') """}