Fixed a couple typos as well as several minor style issues.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7871 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
409ed9468f
commit
96a47da015
|
@ -3,6 +3,10 @@ import types
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from itertools import izip
|
from itertools import izip
|
||||||
|
try:
|
||||||
|
set
|
||||||
|
except NameError:
|
||||||
|
from sets import Set as set # Python 2.3 fallback.
|
||||||
|
|
||||||
import django.db.models.manipulators # Imported to register signal handler.
|
import django.db.models.manipulators # Imported to register signal handler.
|
||||||
import django.db.models.manager # Ditto.
|
import django.db.models.manager # Ditto.
|
||||||
|
@ -23,13 +27,11 @@ from django.core.files.move import file_move_safe
|
||||||
from django.core.files import locks
|
from django.core.files import locks
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
try:
|
|
||||||
set
|
|
||||||
except NameError:
|
|
||||||
from sets import Set as set # Python 2.3 fallback
|
|
||||||
|
|
||||||
class ModelBase(type):
|
class ModelBase(type):
|
||||||
"Metaclass for all models"
|
"""
|
||||||
|
Metaclass for all models.
|
||||||
|
"""
|
||||||
def __new__(cls, name, bases, attrs):
|
def __new__(cls, name, bases, attrs):
|
||||||
super_new = super(ModelBase, cls).__new__
|
super_new = super(ModelBase, cls).__new__
|
||||||
parents = [b for b in bases if isinstance(b, ModelBase)]
|
parents = [b for b in bases if isinstance(b, ModelBase)]
|
||||||
|
@ -144,7 +146,9 @@ class ModelBase(type):
|
||||||
setattr(cls, name, value)
|
setattr(cls, name, value)
|
||||||
|
|
||||||
def _prepare(cls):
|
def _prepare(cls):
|
||||||
# Creates some methods once self._meta has been populated.
|
"""
|
||||||
|
Creates some methods once self._meta has been populated.
|
||||||
|
"""
|
||||||
opts = cls._meta
|
opts = cls._meta
|
||||||
opts._prepare(cls)
|
opts._prepare(cls)
|
||||||
|
|
||||||
|
@ -163,6 +167,7 @@ class ModelBase(type):
|
||||||
|
|
||||||
dispatcher.send(signal=signals.class_prepared, sender=cls)
|
dispatcher.send(signal=signals.class_prepared, sender=cls)
|
||||||
|
|
||||||
|
|
||||||
class Model(object):
|
class Model(object):
|
||||||
__metaclass__ = ModelBase
|
__metaclass__ = ModelBase
|
||||||
|
|
||||||
|
@ -267,7 +272,7 @@ class Model(object):
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""
|
"""
|
||||||
Save the current instance. Override this in a subclass if you want to
|
Saves the current instance. Override this in a subclass if you want to
|
||||||
control the saving process.
|
control the saving process.
|
||||||
"""
|
"""
|
||||||
self.save_base()
|
self.save_base()
|
||||||
|
@ -293,7 +298,7 @@ class Model(object):
|
||||||
|
|
||||||
# If we are in a raw save, save the object exactly as presented.
|
# If we are in a raw save, save the object exactly as presented.
|
||||||
# That means that we don't try to be smart about saving attributes
|
# That means that we don't try to be smart about saving attributes
|
||||||
# that might have come from the parent class - we just save the
|
# that might have come from the parent class - we just save the
|
||||||
# attributes we have been given to the class we have been given.
|
# attributes we have been given to the class we have been given.
|
||||||
if not raw:
|
if not raw:
|
||||||
for parent, field in meta.parents.items():
|
for parent, field in meta.parents.items():
|
||||||
|
@ -301,7 +306,7 @@ class Model(object):
|
||||||
setattr(self, field.attname, self._get_pk_val(parent._meta))
|
setattr(self, field.attname, self._get_pk_val(parent._meta))
|
||||||
|
|
||||||
non_pks = [f for f in meta.local_fields if not f.primary_key]
|
non_pks = [f for f in meta.local_fields if not f.primary_key]
|
||||||
|
|
||||||
# First, try an UPDATE. If that doesn't update anything, do an INSERT.
|
# First, try an UPDATE. If that doesn't update anything, do an INSERT.
|
||||||
pk_val = self._get_pk_val(meta)
|
pk_val = self._get_pk_val(meta)
|
||||||
# Note: the comparison with '' is required for compatibility with
|
# Note: the comparison with '' is required for compatibility with
|
||||||
|
@ -371,10 +376,12 @@ class Model(object):
|
||||||
|
|
||||||
def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
|
def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
|
||||||
"""
|
"""
|
||||||
Recursively populates seen_objs with all objects related to this object.
|
Recursively populates seen_objs with all objects related to this
|
||||||
|
object.
|
||||||
|
|
||||||
When done, seen_objs.items() will be in the format:
|
When done, seen_objs.items() will be in the format:
|
||||||
[(model_class, {pk_val: obj, pk_val: obj, ...}),
|
[(model_class, {pk_val: obj, pk_val: obj, ...}),
|
||||||
(model_class, {pk_val: obj, pk_val: obj, ...}),...]
|
(model_class, {pk_val: obj, pk_val: obj, ...}), ...]
|
||||||
"""
|
"""
|
||||||
pk_val = self._get_pk_val()
|
pk_val = self._get_pk_val()
|
||||||
if seen_objs.add(self.__class__, pk_val, self, parent, nullable):
|
if seen_objs.add(self.__class__, pk_val, self, parent, nullable):
|
||||||
|
@ -411,11 +418,11 @@ class Model(object):
|
||||||
def delete(self):
|
def delete(self):
|
||||||
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
|
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
|
||||||
|
|
||||||
# Find all the objects than need to be deleted
|
# Find all the objects than need to be deleted.
|
||||||
seen_objs = CollectedObjects()
|
seen_objs = CollectedObjects()
|
||||||
self._collect_sub_objects(seen_objs)
|
self._collect_sub_objects(seen_objs)
|
||||||
|
|
||||||
# Actually delete the objects
|
# Actually delete the objects.
|
||||||
delete_objects(seen_objs)
|
delete_objects(seen_objs)
|
||||||
|
|
||||||
delete.alters_data = True
|
delete.alters_data = True
|
||||||
|
@ -454,12 +461,12 @@ class Model(object):
|
||||||
return getattr(self, cachename)
|
return getattr(self, cachename)
|
||||||
|
|
||||||
def _get_FIELD_filename(self, field):
|
def _get_FIELD_filename(self, field):
|
||||||
if getattr(self, field.attname): # value is not blank
|
if getattr(self, field.attname): # Value is not blank.
|
||||||
return os.path.normpath(os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname)))
|
return os.path.normpath(os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname)))
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def _get_FIELD_url(self, field):
|
def _get_FIELD_url(self, field):
|
||||||
if getattr(self, field.attname): # value is not blank
|
if getattr(self, field.attname): # Value is not blank.
|
||||||
import urlparse
|
import urlparse
|
||||||
return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/')
|
return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/')
|
||||||
return ''
|
return ''
|
||||||
|
@ -474,16 +481,14 @@ class Model(object):
|
||||||
except OSError: # Directory probably already exists.
|
except OSError: # Directory probably already exists.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#
|
|
||||||
# Check for old-style usage (files-as-dictionaries). Warn here first
|
# Check for old-style usage (files-as-dictionaries). Warn here first
|
||||||
# since there are multiple locations where we need to support both new
|
# since there are multiple locations where we need to support both new
|
||||||
# and old usage.
|
# and old usage.
|
||||||
#
|
|
||||||
if isinstance(raw_field, dict):
|
if isinstance(raw_field, dict):
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
message = "Representing uploaded files as dictionaries is"\
|
message = "Representing uploaded files as dictionaries is"\
|
||||||
" deprected. Use django.core.files.SimpleUploadedFile"\
|
" deprecated. Use django.core.files.SimpleUploadedFile"\
|
||||||
" instead.",
|
" instead.",
|
||||||
category = DeprecationWarning,
|
category = DeprecationWarning,
|
||||||
stacklevel = 2
|
stacklevel = 2
|
||||||
|
@ -508,30 +513,23 @@ class Model(object):
|
||||||
|
|
||||||
filename = field.get_filename(filename)
|
filename = field.get_filename(filename)
|
||||||
|
|
||||||
#
|
# If the filename already exists, keep adding an underscore to the name
|
||||||
# If the filename already exists, keep adding an underscore to the name of
|
# of the file until the filename doesn't exist.
|
||||||
# the file until the filename doesn't exist.
|
|
||||||
#
|
|
||||||
while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):
|
while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):
|
||||||
try:
|
try:
|
||||||
dot_index = filename.rindex('.')
|
dot_index = filename.rindex('.')
|
||||||
except ValueError: # filename has no dot
|
except ValueError: # filename has no dot.
|
||||||
filename += '_'
|
filename += '_'
|
||||||
else:
|
else:
|
||||||
filename = filename[:dot_index] + '_' + filename[dot_index:]
|
filename = filename[:dot_index] + '_' + filename[dot_index:]
|
||||||
#
|
|
||||||
# Save the file name on the object and write the file to disk
|
|
||||||
#
|
|
||||||
|
|
||||||
|
# Save the file name on the object and write the file to disk.
|
||||||
setattr(self, field.attname, filename)
|
setattr(self, field.attname, filename)
|
||||||
|
|
||||||
full_filename = self._get_FIELD_filename(field)
|
full_filename = self._get_FIELD_filename(field)
|
||||||
|
|
||||||
if hasattr(raw_field, 'temporary_file_path'):
|
if hasattr(raw_field, 'temporary_file_path'):
|
||||||
# This file has a file path that we can move.
|
# This file has a file path that we can move.
|
||||||
raw_field.close()
|
raw_field.close()
|
||||||
file_move_safe(raw_field.temporary_file_path(), full_filename)
|
file_move_safe(raw_field.temporary_file_path(), full_filename)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# This is a normal uploadedfile that we can stream.
|
# This is a normal uploadedfile that we can stream.
|
||||||
fp = open(full_filename, 'wb')
|
fp = open(full_filename, 'wb')
|
||||||
|
@ -542,7 +540,8 @@ class Model(object):
|
||||||
fp.close()
|
fp.close()
|
||||||
|
|
||||||
# Save the width and/or height, if applicable.
|
# Save the width and/or height, if applicable.
|
||||||
if isinstance(field, ImageField) and (field.width_field or field.height_field):
|
if isinstance(field, ImageField) and \
|
||||||
|
(field.width_field or field.height_field):
|
||||||
from django.utils.images import get_image_dimensions
|
from django.utils.images import get_image_dimensions
|
||||||
width, height = get_image_dimensions(full_filename)
|
width, height = get_image_dimensions(full_filename)
|
||||||
if field.width_field:
|
if field.width_field:
|
||||||
|
@ -550,7 +549,7 @@ class Model(object):
|
||||||
if field.height_field:
|
if field.height_field:
|
||||||
setattr(self, field.height_field, height)
|
setattr(self, field.height_field, height)
|
||||||
|
|
||||||
# Save the object because it has changed unless save is False
|
# Save the object because it has changed, unless save is False.
|
||||||
if save:
|
if save:
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
@ -570,6 +569,7 @@ class Model(object):
|
||||||
setattr(self, cachename, get_image_dimensions(filename))
|
setattr(self, cachename, get_image_dimensions(filename))
|
||||||
return getattr(self, cachename)
|
return getattr(self, cachename)
|
||||||
|
|
||||||
|
|
||||||
############################################
|
############################################
|
||||||
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
|
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
|
||||||
############################################
|
############################################
|
||||||
|
@ -585,6 +585,7 @@ def method_set_order(ordered_obj, self, id_list):
|
||||||
ordered_obj.objects.filter(**{'pk': j, order_name: rel_val}).update(_order=i)
|
ordered_obj.objects.filter(**{'pk': j, order_name: rel_val}).update(_order=i)
|
||||||
transaction.commit_unless_managed()
|
transaction.commit_unless_managed()
|
||||||
|
|
||||||
|
|
||||||
def method_get_order(ordered_obj, self):
|
def method_get_order(ordered_obj, self):
|
||||||
rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
|
rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
|
||||||
order_name = ordered_obj._meta.order_with_respect_to.name
|
order_name = ordered_obj._meta.order_with_respect_to.name
|
||||||
|
@ -592,6 +593,7 @@ def method_get_order(ordered_obj, self):
|
||||||
return [r[pk_name] for r in
|
return [r[pk_name] for r in
|
||||||
ordered_obj.objects.filter(**{order_name: rel_val}).values(pk_name)]
|
ordered_obj.objects.filter(**{order_name: rel_val}).values(pk_name)]
|
||||||
|
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
# HELPER FUNCTIONS (CURRIED MODEL FUNCTIONS) #
|
# HELPER FUNCTIONS (CURRIED MODEL FUNCTIONS) #
|
||||||
##############################################
|
##############################################
|
||||||
|
@ -599,6 +601,7 @@ def method_get_order(ordered_obj, self):
|
||||||
def get_absolute_url(opts, func, self, *args, **kwargs):
|
def get_absolute_url(opts, func, self, *args, **kwargs):
|
||||||
return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self, *args, **kwargs)
|
return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
########
|
########
|
||||||
# MISC #
|
# MISC #
|
||||||
########
|
########
|
||||||
|
@ -610,8 +613,6 @@ if sys.version_info < (2, 5):
|
||||||
# Prior to Python 2.5, Exception was an old-style class
|
# Prior to Python 2.5, Exception was an old-style class
|
||||||
def subclass_exception(name, parent, unused):
|
def subclass_exception(name, parent, unused):
|
||||||
return types.ClassType(name, (parent,), {})
|
return types.ClassType(name, (parent,), {})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
def subclass_exception(name, parent, module):
|
def subclass_exception(name, parent, module):
|
||||||
return type(name, (parent,), {'__module__': module})
|
return type(name, (parent,), {'__module__': module})
|
||||||
|
|
||||||
|
|
|
@ -13,19 +13,20 @@ from django.utils.datastructures import SortedDict
|
||||||
CHUNK_SIZE = 100
|
CHUNK_SIZE = 100
|
||||||
ITER_CHUNK_SIZE = CHUNK_SIZE
|
ITER_CHUNK_SIZE = CHUNK_SIZE
|
||||||
|
|
||||||
# Pull into this namespace for backwards compatibility
|
# Pull into this namespace for backwards compatibility.
|
||||||
EmptyResultSet = sql.EmptyResultSet
|
EmptyResultSet = sql.EmptyResultSet
|
||||||
|
|
||||||
class CyclicDependency(Exception):
|
class CyclicDependency(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CollectedObjects(object):
|
class CollectedObjects(object):
|
||||||
"""
|
"""
|
||||||
A container that stores keys and lists of values along with
|
A container that stores keys and lists of values along with remembering the
|
||||||
remembering the parent objects for all the keys.
|
parent objects for all the keys.
|
||||||
|
|
||||||
This is used for the database object deletion routines so that we
|
This is used for the database object deletion routines so that we can
|
||||||
can calculate the 'leaf' objects which should be deleted first.
|
calculate the 'leaf' objects which should be deleted first.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -34,26 +35,27 @@ class CollectedObjects(object):
|
||||||
|
|
||||||
def add(self, model, pk, obj, parent_model, nullable=False):
|
def add(self, model, pk, obj, parent_model, nullable=False):
|
||||||
"""
|
"""
|
||||||
Adds an item.
|
Adds an item to the container.
|
||||||
model is the class of the object being added,
|
|
||||||
pk is the primary key, obj is the object itself,
|
|
||||||
parent_model is the model of the parent object
|
|
||||||
that this object was reached through, nullable should
|
|
||||||
be True if this relation is nullable.
|
|
||||||
|
|
||||||
If the item already existed in the structure,
|
Arguments:
|
||||||
returns true, otherwise false.
|
* model - the class of the object being added.
|
||||||
|
* pk - the primary key.
|
||||||
|
* obj - the object itself.
|
||||||
|
* parent_model - the model of the parent object that this object was
|
||||||
|
reached through.
|
||||||
|
* nullable - should be True if this relation is nullable.
|
||||||
|
|
||||||
|
Returns True if the item already existed in the structure and
|
||||||
|
False otherwise.
|
||||||
"""
|
"""
|
||||||
d = self.data.setdefault(model, SortedDict())
|
d = self.data.setdefault(model, SortedDict())
|
||||||
retval = pk in d
|
retval = pk in d
|
||||||
d[pk] = obj
|
d[pk] = obj
|
||||||
# Nullable relationships can be ignored -- they
|
# Nullable relationships can be ignored -- they are nulled out before
|
||||||
# are nulled out before deleting, and therefore
|
# deleting, and therefore do not affect the order in which objects
|
||||||
# do not affect the order in which objects have
|
# have to be deleted.
|
||||||
# to be deleted.
|
|
||||||
if parent_model is not None and not nullable:
|
if parent_model is not None and not nullable:
|
||||||
self.children.setdefault(parent_model, []).append(model)
|
self.children.setdefault(parent_model, []).append(model)
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
|
@ -77,8 +79,8 @@ class CollectedObjects(object):
|
||||||
|
|
||||||
def ordered_keys(self):
|
def ordered_keys(self):
|
||||||
"""
|
"""
|
||||||
Returns the models in the order that they should be
|
Returns the models in the order that they should be dealt with (i.e.
|
||||||
dealth with i.e. models with no dependencies first.
|
models with no dependencies first).
|
||||||
"""
|
"""
|
||||||
dealt_with = SortedDict()
|
dealt_with = SortedDict()
|
||||||
# Start with items that have no children
|
# Start with items that have no children
|
||||||
|
@ -91,19 +93,22 @@ class CollectedObjects(object):
|
||||||
dealt_with[model] = None
|
dealt_with[model] = None
|
||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
raise CyclicDependency("There is a cyclic dependency of items to be processed.")
|
raise CyclicDependency(
|
||||||
|
"There is a cyclic dependency of items to be processed.")
|
||||||
|
|
||||||
return dealt_with.keys()
|
return dealt_with.keys()
|
||||||
|
|
||||||
def unordered_keys(self):
|
def unordered_keys(self):
|
||||||
"""
|
"""
|
||||||
Fallback for the case where is a cyclic dependency but we
|
Fallback for the case where is a cyclic dependency but we don't care.
|
||||||
don't care.
|
|
||||||
"""
|
"""
|
||||||
return self.data.keys()
|
return self.data.keys()
|
||||||
|
|
||||||
|
|
||||||
class QuerySet(object):
|
class QuerySet(object):
|
||||||
"Represents a lazy database lookup for a set of objects"
|
"""
|
||||||
|
Represents a lazy database lookup for a set of objects.
|
||||||
|
"""
|
||||||
def __init__(self, model=None, query=None):
|
def __init__(self, model=None, query=None):
|
||||||
self.model = model
|
self.model = model
|
||||||
self.query = query or sql.Query(self.model, connection)
|
self.query = query or sql.Query(self.model, connection)
|
||||||
|
@ -116,7 +121,7 @@ class QuerySet(object):
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
"""
|
"""
|
||||||
Allows the Queryset to be pickled.
|
Allows the QuerySet to be pickled.
|
||||||
"""
|
"""
|
||||||
# Force the cache to be fully populated.
|
# Force the cache to be fully populated.
|
||||||
len(self)
|
len(self)
|
||||||
|
@ -131,7 +136,7 @@ class QuerySet(object):
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
# Since __len__ is called quite frequently (for example, as part of
|
# Since __len__ is called quite frequently (for example, as part of
|
||||||
# list(qs), we make some effort here to be as efficient as possible
|
# list(qs), we make some effort here to be as efficient as possible
|
||||||
# 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)
|
||||||
|
@ -173,7 +178,9 @@ class QuerySet(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __getitem__(self, k):
|
def __getitem__(self, k):
|
||||||
"Retrieve an item or slice from the set of results."
|
"""
|
||||||
|
Retrieves an item or slice from the set of results.
|
||||||
|
"""
|
||||||
if not isinstance(k, (slice, int, long)):
|
if not isinstance(k, (slice, int, long)):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
assert ((not isinstance(k, slice) and (k >= 0))
|
assert ((not isinstance(k, slice) and (k >= 0))
|
||||||
|
@ -264,7 +271,7 @@ class QuerySet(object):
|
||||||
Performs a SELECT COUNT() and returns the number of records as an
|
Performs a SELECT COUNT() and returns the number of records as an
|
||||||
integer.
|
integer.
|
||||||
|
|
||||||
If the queryset is already cached (i.e. self._result_cache is set) this
|
If the QuerySet is already cached (i.e. self._result_cache is set) this
|
||||||
simply returns the length of the cached results set to avoid multiple
|
simply returns the length of the cached results set to avoid multiple
|
||||||
SELECT COUNT(*) calls.
|
SELECT COUNT(*) calls.
|
||||||
"""
|
"""
|
||||||
|
@ -290,7 +297,7 @@ class QuerySet(object):
|
||||||
|
|
||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
Create a new object with the given kwargs, saving it to the database
|
Creates a new object with the given kwargs, saving it to the database
|
||||||
and returning the created object.
|
and returning the created object.
|
||||||
"""
|
"""
|
||||||
obj = self.model(**kwargs)
|
obj = self.model(**kwargs)
|
||||||
|
@ -425,8 +432,8 @@ class QuerySet(object):
|
||||||
|
|
||||||
def dates(self, field_name, kind, order='ASC'):
|
def dates(self, field_name, kind, order='ASC'):
|
||||||
"""
|
"""
|
||||||
Returns a list of datetime objects representing all available dates
|
Returns a list of datetime objects representing all available dates for
|
||||||
for the given field_name, scoped to 'kind'.
|
the given field_name, scoped to 'kind'.
|
||||||
"""
|
"""
|
||||||
assert kind in ("month", "year", "day"), \
|
assert kind in ("month", "year", "day"), \
|
||||||
"'kind' must be one of 'year', 'month' or 'day'."
|
"'kind' must be one of 'year', 'month' or 'day'."
|
||||||
|
@ -441,7 +448,7 @@ class QuerySet(object):
|
||||||
|
|
||||||
def none(self):
|
def none(self):
|
||||||
"""
|
"""
|
||||||
Returns an empty queryset.
|
Returns an empty QuerySet.
|
||||||
"""
|
"""
|
||||||
return self._clone(klass=EmptyQuerySet)
|
return self._clone(klass=EmptyQuerySet)
|
||||||
|
|
||||||
|
@ -485,6 +492,7 @@ class QuerySet(object):
|
||||||
def complex_filter(self, filter_obj):
|
def complex_filter(self, filter_obj):
|
||||||
"""
|
"""
|
||||||
Returns a new QuerySet instance with filter_obj added to the filters.
|
Returns a new QuerySet instance with filter_obj added to the filters.
|
||||||
|
|
||||||
filter_obj can be a Q object (or anything with an add_to_query()
|
filter_obj can be a Q object (or anything with an add_to_query()
|
||||||
method) or a dictionary of keyword lookup arguments.
|
method) or a dictionary of keyword lookup arguments.
|
||||||
|
|
||||||
|
@ -500,8 +508,9 @@ class QuerySet(object):
|
||||||
|
|
||||||
def select_related(self, *fields, **kwargs):
|
def select_related(self, *fields, **kwargs):
|
||||||
"""
|
"""
|
||||||
Returns a new QuerySet instance that will select related objects. If
|
Returns a new QuerySet instance that will select related objects.
|
||||||
fields are specified, they must be ForeignKey fields and only those
|
|
||||||
|
If fields are specified, they must be ForeignKey fields and only those
|
||||||
related objects are included in the selection.
|
related objects are included in the selection.
|
||||||
"""
|
"""
|
||||||
depth = kwargs.pop('depth', 0)
|
depth = kwargs.pop('depth', 0)
|
||||||
|
@ -521,13 +530,15 @@ class QuerySet(object):
|
||||||
|
|
||||||
def dup_select_related(self, other):
|
def dup_select_related(self, other):
|
||||||
"""
|
"""
|
||||||
Copies the related selection status from the queryset 'other' to the
|
Copies the related selection status from the QuerySet 'other' to the
|
||||||
current queryset.
|
current QuerySet.
|
||||||
"""
|
"""
|
||||||
self.query.select_related = other.query.select_related
|
self.query.select_related = other.query.select_related
|
||||||
|
|
||||||
def order_by(self, *field_names):
|
def order_by(self, *field_names):
|
||||||
"""Returns a new QuerySet instance with the ordering changed."""
|
"""
|
||||||
|
Returns a new QuerySet instance with the ordering changed.
|
||||||
|
"""
|
||||||
assert self.query.can_filter(), \
|
assert self.query.can_filter(), \
|
||||||
"Cannot reorder a query once a slice has been taken."
|
"Cannot reorder a query once a slice has been taken."
|
||||||
obj = self._clone()
|
obj = self._clone()
|
||||||
|
@ -544,9 +555,9 @@ class QuerySet(object):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def extra(self, select=None, where=None, params=None, tables=None,
|
def extra(self, select=None, where=None, params=None, tables=None,
|
||||||
order_by=None, select_params=None):
|
order_by=None, select_params=None):
|
||||||
"""
|
"""
|
||||||
Add extra SQL fragments to the query.
|
Adds extra SQL fragments to the query.
|
||||||
"""
|
"""
|
||||||
assert self.query.can_filter(), \
|
assert self.query.can_filter(), \
|
||||||
"Cannot change a query once a slice has been taken"
|
"Cannot change a query once a slice has been taken"
|
||||||
|
@ -556,7 +567,7 @@ class QuerySet(object):
|
||||||
|
|
||||||
def reverse(self):
|
def reverse(self):
|
||||||
"""
|
"""
|
||||||
Reverses the ordering of the queryset.
|
Reverses the ordering of the QuerySet.
|
||||||
"""
|
"""
|
||||||
clone = self._clone()
|
clone = self._clone()
|
||||||
clone.query.standard_ordering = not clone.query.standard_ordering
|
clone.query.standard_ordering = not clone.query.standard_ordering
|
||||||
|
@ -589,12 +600,13 @@ class QuerySet(object):
|
||||||
|
|
||||||
def _merge_sanity_check(self, other):
|
def _merge_sanity_check(self, other):
|
||||||
"""
|
"""
|
||||||
Checks that we are merging two comparable queryset classes. By default
|
Checks that we are merging two comparable QuerySet classes. By default
|
||||||
this does nothing, but see the ValuesQuerySet for an example of where
|
this does nothing, but see the ValuesQuerySet for an example of where
|
||||||
it's useful.
|
it's useful.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ValuesQuerySet(QuerySet):
|
class ValuesQuerySet(QuerySet):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ValuesQuerySet, self).__init__(*args, **kwargs)
|
super(ValuesQuerySet, self).__init__(*args, **kwargs)
|
||||||
|
@ -617,7 +629,7 @@ class ValuesQuerySet(QuerySet):
|
||||||
Constructs the field_names list that the values query will be
|
Constructs the field_names list that the values query will be
|
||||||
retrieving.
|
retrieving.
|
||||||
|
|
||||||
Called by the _clone() method after initialising the rest of the
|
Called by the _clone() method after initializing the rest of the
|
||||||
instance.
|
instance.
|
||||||
"""
|
"""
|
||||||
self.extra_names = []
|
self.extra_names = []
|
||||||
|
@ -658,6 +670,7 @@ class ValuesQuerySet(QuerySet):
|
||||||
raise TypeError("Merging '%s' classes must involve the same values in each case."
|
raise TypeError("Merging '%s' classes must involve the same values in each case."
|
||||||
% self.__class__.__name__)
|
% self.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
class ValuesListQuerySet(ValuesQuerySet):
|
class ValuesListQuerySet(ValuesQuerySet):
|
||||||
def iterator(self):
|
def iterator(self):
|
||||||
self.query.trim_extra_select(self.extra_names)
|
self.query.trim_extra_select(self.extra_names)
|
||||||
|
@ -681,6 +694,7 @@ class ValuesListQuerySet(ValuesQuerySet):
|
||||||
clone.flat = self.flat
|
clone.flat = self.flat
|
||||||
return clone
|
return clone
|
||||||
|
|
||||||
|
|
||||||
class DateQuerySet(QuerySet):
|
class DateQuerySet(QuerySet):
|
||||||
def iterator(self):
|
def iterator(self):
|
||||||
return self.query.results_iter()
|
return self.query.results_iter()
|
||||||
|
@ -689,7 +703,7 @@ class DateQuerySet(QuerySet):
|
||||||
"""
|
"""
|
||||||
Sets up any special features of the query attribute.
|
Sets up any special features of the query attribute.
|
||||||
|
|
||||||
Called by the _clone() method after initialising the rest of the
|
Called by the _clone() method after initializing the rest of the
|
||||||
instance.
|
instance.
|
||||||
"""
|
"""
|
||||||
self.query = self.query.clone(klass=sql.DateQuery, setup=True)
|
self.query = self.query.clone(klass=sql.DateQuery, setup=True)
|
||||||
|
@ -706,6 +720,7 @@ class DateQuerySet(QuerySet):
|
||||||
c._setup_query()
|
c._setup_query()
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
class EmptyQuerySet(QuerySet):
|
class EmptyQuerySet(QuerySet):
|
||||||
def __init__(self, model=None, query=None):
|
def __init__(self, model=None, query=None):
|
||||||
super(EmptyQuerySet, self).__init__(model, query)
|
super(EmptyQuerySet, self).__init__(model, query)
|
||||||
|
@ -733,6 +748,7 @@ class EmptyQuerySet(QuerySet):
|
||||||
# (it raises StopIteration immediately).
|
# (it raises StopIteration immediately).
|
||||||
yield iter([]).next()
|
yield iter([]).next()
|
||||||
|
|
||||||
|
|
||||||
# QOperator, QNot, QAnd and QOr are temporarily retained for backwards
|
# QOperator, QNot, QAnd and QOr are temporarily retained for backwards
|
||||||
# compatibility. All the old functionality is now part of the 'Q' class.
|
# compatibility. All the old functionality is now part of the 'Q' class.
|
||||||
class QOperator(Q):
|
class QOperator(Q):
|
||||||
|
@ -743,12 +759,14 @@ class QOperator(Q):
|
||||||
|
|
||||||
QOr = QAnd = QOperator
|
QOr = QAnd = QOperator
|
||||||
|
|
||||||
|
|
||||||
def QNot(q):
|
def QNot(q):
|
||||||
warnings.warn('Use ~q instead of QNot(q)', DeprecationWarning, stacklevel=2)
|
warnings.warn('Use ~q instead of QNot(q)', DeprecationWarning, stacklevel=2)
|
||||||
return ~q
|
return ~q
|
||||||
|
|
||||||
|
|
||||||
def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
|
def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
|
||||||
requested=None):
|
requested=None):
|
||||||
"""
|
"""
|
||||||
Helper function that recursively returns an object with the specified
|
Helper function that recursively returns an object with the specified
|
||||||
related attributes already populated.
|
related attributes already populated.
|
||||||
|
@ -774,6 +792,7 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
|
||||||
setattr(obj, f.get_cache_name(), rel_obj)
|
setattr(obj, f.get_cache_name(), rel_obj)
|
||||||
return obj, index_end
|
return obj, index_end
|
||||||
|
|
||||||
|
|
||||||
def delete_objects(seen_objs):
|
def delete_objects(seen_objs):
|
||||||
"""
|
"""
|
||||||
Iterate through a list of seen classes, and remove any instances that are
|
Iterate through a list of seen classes, and remove any instances that are
|
||||||
|
@ -782,10 +801,10 @@ def delete_objects(seen_objs):
|
||||||
try:
|
try:
|
||||||
ordered_classes = seen_objs.keys()
|
ordered_classes = seen_objs.keys()
|
||||||
except CyclicDependency:
|
except CyclicDependency:
|
||||||
# if there is a cyclic dependency, we cannot in general delete
|
# If there is a cyclic dependency, we cannot in general delete the
|
||||||
# the objects. However, if an appropriate transaction is set
|
# objects. However, if an appropriate transaction is set up, or if the
|
||||||
# up, or if the database is lax enough, it will succeed.
|
# database is lax enough, it will succeed. So for now, we go ahead and
|
||||||
# So for now, we go ahead and try anway.
|
# try anyway.
|
||||||
ordered_classes = seen_objs.unordered_keys()
|
ordered_classes = seen_objs.unordered_keys()
|
||||||
|
|
||||||
obj_pairs = {}
|
obj_pairs = {}
|
||||||
|
@ -794,7 +813,7 @@ def delete_objects(seen_objs):
|
||||||
items.sort()
|
items.sort()
|
||||||
obj_pairs[cls] = items
|
obj_pairs[cls] = items
|
||||||
|
|
||||||
# Pre notify all instances to be deleted
|
# Pre-notify all instances to be deleted.
|
||||||
for pk_val, instance in items:
|
for pk_val, instance in items:
|
||||||
dispatcher.send(signal=signals.pre_delete, sender=cls,
|
dispatcher.send(signal=signals.pre_delete, sender=cls,
|
||||||
instance=instance)
|
instance=instance)
|
||||||
|
@ -808,7 +827,7 @@ def delete_objects(seen_objs):
|
||||||
if field.rel and field.null and field.rel.to in seen_objs:
|
if field.rel and field.null and field.rel.to in seen_objs:
|
||||||
update_query.clear_related(field, pk_list)
|
update_query.clear_related(field, pk_list)
|
||||||
|
|
||||||
# Now delete the actual data
|
# Now delete the actual data.
|
||||||
for cls in ordered_classes:
|
for cls in ordered_classes:
|
||||||
items = obj_pairs[cls]
|
items = obj_pairs[cls]
|
||||||
items.reverse()
|
items.reverse()
|
||||||
|
@ -831,6 +850,7 @@ def delete_objects(seen_objs):
|
||||||
|
|
||||||
transaction.commit_unless_managed()
|
transaction.commit_unless_managed()
|
||||||
|
|
||||||
|
|
||||||
def insert_query(model, values, return_id=False, raw_values=False):
|
def insert_query(model, values, return_id=False, raw_values=False):
|
||||||
"""
|
"""
|
||||||
Inserts a new record for the given model. This provides an interface to
|
Inserts a new record for the given model. This provides an interface to
|
||||||
|
@ -840,4 +860,3 @@ def insert_query(model, values, return_id=False, raw_values=False):
|
||||||
query = sql.InsertQuery(model, connection)
|
query = sql.InsertQuery(model, connection)
|
||||||
query.insert_values(values, raw_values)
|
query.insert_values(values, raw_values)
|
||||||
return query.execute_sql(return_id)
|
return query.execute_sql(return_id)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue