1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

gis: Merged revisions 7499,7501-7502,7504,7509-7510 via svnmerge from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7511 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2008-05-01 00:32:50 +00:00
parent e5b52f90f0
commit 5922dabea0
8 changed files with 98 additions and 38 deletions

View File

@ -237,32 +237,6 @@ class Model(object):
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0] 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) 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): def __repr__(self):
return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self))) return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))

View File

@ -28,6 +28,17 @@ class QuerySet(object):
# PYTHON MAGIC METHODS # # PYTHON MAGIC METHODS #
######################## ########################
def __getstate__(self):
"""
Allows the Queryset to be pickled.
"""
# Force the cache to be fully populated.
len(self)
obj_dict = self.__dict__.copy()
obj_dict['_iter'] = None
return obj_dict
def __repr__(self): def __repr__(self):
return repr(list(self)) return repr(list(self))
@ -37,7 +48,7 @@ class QuerySet(object):
# whilst not messing up any existing iterators against the queryset. # whilst not messing up any existing iterators against the queryset.
if self._result_cache is None: if self._result_cache is None:
if self._iter: if self._iter:
self._result_cache = list(self._iter()) self._result_cache = list(self._iter)
else: else:
self._result_cache = list(self.iterator()) self._result_cache = list(self.iterator())
elif self._iter: elif self._iter:
@ -153,7 +164,7 @@ class QuerySet(object):
obj, _ = get_cached_row(self.model, row, index_start, obj, _ = get_cached_row(self.model, row, index_start,
max_depth, requested=requested) max_depth, requested=requested)
else: else:
obj = self.model.from_sequence(row[index_start:]) obj = self.model(*row[index_start:])
for i, k in enumerate(extra_select): for i, k in enumerate(extra_select):
setattr(obj, k, row[i]) setattr(obj, k, row[i])
yield obj yield obj
@ -644,7 +655,7 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
restricted = requested is not None restricted = requested is not None
index_end = index_start + len(klass._meta.fields) 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: for f in klass._meta.fields:
if (not f.rel or (not restricted and f.null) or if (not f.rel or (not restricted and f.null) or
(restricted and f.name not in requested) or f.rel.parent_link): (restricted and f.name not in requested) or f.rel.parent_link):

View File

@ -99,6 +99,24 @@ class Query(object):
memo[id(self)] = result memo[id(self)] = result
return result return result
def __getstate__(self):
"""
Pickling support.
"""
obj_dict = self.__dict__.copy()
del obj_dict['connection']
return obj_dict
def __setstate__(self, obj_dict):
"""
Unpickling support.
"""
self.__dict__.update(obj_dict)
# XXX: Need a better solution for this when multi-db stuff is
# supported. It's the only class-reference to the module-level
# connection variable.
self.connection = connection
def get_meta(self): def get_meta(self):
""" """
Returns the Options instance (the model._meta) from which to start Returns the Options instance (the model._meta) from which to start
@ -376,7 +394,8 @@ class Query(object):
some cases to avoid ambiguitity with nested queries. some cases to avoid ambiguitity with nested queries.
""" """
qn = self.quote_name_unless_alias 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()) aliases = set(self.extra_select.keys())
if with_aliases: if with_aliases:
col_aliases = aliases.copy() col_aliases = aliases.copy()

View File

@ -51,12 +51,12 @@ class WhereNode(tree.Node):
format = '(%s)' format = '(%s)'
elif isinstance(child, tree.Node): elif isinstance(child, tree.Node):
sql, params = self.as_sql(child, qn) 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' format = '%s'
else: else:
format = '(%s)' format = '(%s)'
if child.negated:
format = 'NOT %s' % format
else: else:
sql, params = self.make_atom(child, qn) sql, params = self.make_atom(child, qn)
format = '%s' format = '%s'

View File

@ -376,6 +376,29 @@ You can evaluate a ``QuerySet`` in the following ways:
iterating over a ``QuerySet`` will take advantage of your database to iterating over a ``QuerySet`` will take advantage of your database to
load data and instantiate objects only as you need them. load data and instantiate objects only as you need them.
Pickling QuerySets
~~~~~~~~~~~~~~~~~~
If you pickle_ a ``QuerySet``, this will also force all the results to be
loaded into memory prior to pickling. This is because pickling is usually used
as a precursor to caching and when the cached queryset is reloaded, you want
the results to already be present. This means that when you unpickle a
``QuerySet``, it contains the results at the moment it was pickled, rather
than the results that are currently in the database.
If you only want to pickle the necessary information to recreate the
``Queryset`` from the database at a later time, pickle the ``query`` attribute
of the ``QuerySet``. You can then recreate the original ``QuerySet`` (without
any results loaded) using some code like this::
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
.. _pickle: http://docs.python.org/lib/module-pickle.html
Limiting QuerySets Limiting QuerySets
------------------ ------------------

View File

@ -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 content, you can't use the ``HttpResponse`` instance as a file-like
object. Doing so will raise ``Exception``. 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 Methods
------- -------
@ -420,7 +441,7 @@ Methods
but since this is actually the value included in the HTTP ``Content-Type`` 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 header, it can also include the character set encoding, which makes it
more than just a MIME type specification. If ``mimetype`` is specified 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. neither is given, the ``DEFAULT_CONTENT_TYPE`` setting is used.
``__setitem__(header, value)`` ``__setitem__(header, value)``

View File

@ -398,4 +398,16 @@ u'\u6797\u539f \u3081\u3050\u307f'
>>> s = set([a10, a11, a12]) >>> s = set([a10, a11, a12])
>>> Article.objects.get(headline='Article 11') in s >>> Article.objects.get(headline='Article 11') in s
True 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
""" """

View File

@ -120,13 +120,13 @@ class LoopZ(models.Model):
# A model and custom default manager combination. # A model and custom default manager combination.
class CustomManager(models.Manager): class CustomManager(models.Manager):
def get_query_set(self): def get_query_set(self):
return super(CustomManager, self).get_query_set().filter(public=True, qs = super(CustomManager, self).get_query_set()
tag__name='t1') return qs.filter(is_public=True, tag__name='t1')
class ManagedModel(models.Model): class ManagedModel(models.Model):
data = models.CharField(max_length=10) data = models.CharField(max_length=10)
tag = models.ForeignKey(Tag) tag = models.ForeignKey(Tag)
public = models.BooleanField(default=True) is_public = models.BooleanField(default=True)
objects = CustomManager() objects = CustomManager()
normal_manager = models.Manager() normal_manager = models.Manager()
@ -698,7 +698,7 @@ More twisted cases, involving nested negations.
Bug #7095 Bug #7095
Updates that are filtered on the model being updated are somewhat tricky to get Updates that are filtered on the model being updated are somewhat tricky to get
in MySQL. This exercises that case. 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') >>> ManagedModel.objects.update(data='mm')
"""} """}