Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

queryset-refactor: Added a Model.from_sequence() constructor for inte…

…rnal and

advanced usage.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7474 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 177f7d51647f4d6be6b840c32a4abbf460ed03be 1 parent 0b30bed
@malcolmt malcolmt authored
Showing with 58 additions and 29 deletions.
  1. +56 −27 django/db/models/base.py
  2. +2 −2 django/db/models/query.py
View
83 django/db/models/base.py
@@ -165,33 +165,6 @@ def _prepare(cls):
class Model(object):
__metaclass__ = ModelBase
- def _get_pk_val(self, meta=None):
- if not meta:
- meta = self._meta
- return getattr(self, meta.pk.attname)
-
- def _set_pk_val(self, value):
- return setattr(self, self._meta.pk.attname, value)
-
- pk = property(_get_pk_val, _set_pk_val)
-
- def __repr__(self):
- return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))
-
- def __str__(self):
- if hasattr(self, '__unicode__'):
- return force_unicode(self).encode('utf-8')
- return '%s object' % self.__class__.__name__
-
- def __eq__(self, other):
- return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __hash__(self):
- return hash(self._get_pk_val())
-
def __init__(self, *args, **kwargs):
dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
@@ -264,6 +237,59 @@ def __init__(self, *args, **kwargs):
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)))
+
+ def __str__(self):
+ if hasattr(self, '__unicode__'):
+ return force_unicode(self).encode('utf-8')
+ return '%s object' % self.__class__.__name__
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return hash(self._get_pk_val())
+
+ def _get_pk_val(self, meta=None):
+ if not meta:
+ meta = self._meta
+ return getattr(self, meta.pk.attname)
+
+ def _set_pk_val(self, value):
+ return setattr(self, self._meta.pk.attname, value)
+
+ pk = property(_get_pk_val, _set_pk_val)
+
def save(self):
"""
Save the current instance. Override this in a subclass if you want to
@@ -533,6 +559,9 @@ def get_absolute_url(opts, func, self, *args, **kwargs):
# MISC #
########
+class Empty(object):
+ pass
+
if sys.version_info < (2, 5):
# Prior to Python 2.5, Exception was an old-style class
def subclass_exception(name, parent, unused):
View
4 django/db/models/query.py
@@ -153,7 +153,7 @@ def iterator(self):
obj, _ = get_cached_row(self.model, row, index_start,
max_depth, requested=requested)
else:
- obj = self.model(*row[index_start:])
+ obj = self.model.from_sequence(row[index_start:])
for i, k in enumerate(extra_select):
setattr(obj, k, row[i])
yield obj
@@ -646,7 +646,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(*row[index_start:index_end])
+ obj = klass.from_sequence(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):

0 comments on commit 177f7d5

Please sign in to comment.
Something went wrong with that request. Please try again.