summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/backends/oracle/query.py8
-rw-r--r--django/db/models/base.py28
-rw-r--r--django/db/models/query.py4
-rw-r--r--django/db/models/sql/query.py3
-rw-r--r--django/db/models/sql/where.py6
-rw-r--r--docs/request_response.txt23
-rw-r--r--tests/modeltests/basic/models.py12
-rw-r--r--tests/regressiontests/queries/models.py8
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')
"""}