Skip to content

Commit 177f7d5

Browse files
committed
queryset-refactor: Added a Model.from_sequence() constructor for internal and
advanced usage. git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7474 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 0b30bed commit 177f7d5

File tree

2 files changed

+58
-29
lines changed

2 files changed

+58
-29
lines changed

django/db/models/base.py

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -165,33 +165,6 @@ def _prepare(cls):
165165
class Model(object):
166166
__metaclass__ = ModelBase
167167

168-
def _get_pk_val(self, meta=None):
169-
if not meta:
170-
meta = self._meta
171-
return getattr(self, meta.pk.attname)
172-
173-
def _set_pk_val(self, value):
174-
return setattr(self, self._meta.pk.attname, value)
175-
176-
pk = property(_get_pk_val, _set_pk_val)
177-
178-
def __repr__(self):
179-
return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))
180-
181-
def __str__(self):
182-
if hasattr(self, '__unicode__'):
183-
return force_unicode(self).encode('utf-8')
184-
return '%s object' % self.__class__.__name__
185-
186-
def __eq__(self, other):
187-
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
188-
189-
def __ne__(self, other):
190-
return not self.__eq__(other)
191-
192-
def __hash__(self):
193-
return hash(self._get_pk_val())
194-
195168
def __init__(self, *args, **kwargs):
196169
dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
197170

@@ -264,6 +237,59 @@ def __init__(self, *args, **kwargs):
264237
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
265238
dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
266239

240+
def from_sequence(cls, values):
241+
"""
242+
An alternate class constructor, primarily for internal use.
243+
244+
Creates a model instance from a sequence of values (which corresponds
245+
to all the non-many-to-many fields in creation order. If there are more
246+
fields than values, the remaining (final) fields are given their
247+
default values.
248+
249+
ForeignKey fields can only be initialised using id values, not
250+
instances, in this method.
251+
"""
252+
dispatcher.send(signal=signals.pre_init, sender=cls, args=values,
253+
kwargs={})
254+
obj = Empty()
255+
obj.__class__ = cls
256+
field_iter = iter(obj._meta.fields)
257+
for val, field in izip(values, field_iter):
258+
setattr(obj, field.attname, val)
259+
for field in field_iter:
260+
setattr(obj, field.attname, field.get_default())
261+
dispatcher.send(signal=signals.post_init, sender=cls, instance=obj)
262+
return obj
263+
264+
from_sequence = classmethod(from_sequence)
265+
266+
def __repr__(self):
267+
return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))
268+
269+
def __str__(self):
270+
if hasattr(self, '__unicode__'):
271+
return force_unicode(self).encode('utf-8')
272+
return '%s object' % self.__class__.__name__
273+
274+
def __eq__(self, other):
275+
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
276+
277+
def __ne__(self, other):
278+
return not self.__eq__(other)
279+
280+
def __hash__(self):
281+
return hash(self._get_pk_val())
282+
283+
def _get_pk_val(self, meta=None):
284+
if not meta:
285+
meta = self._meta
286+
return getattr(self, meta.pk.attname)
287+
288+
def _set_pk_val(self, value):
289+
return setattr(self, self._meta.pk.attname, value)
290+
291+
pk = property(_get_pk_val, _set_pk_val)
292+
267293
def save(self):
268294
"""
269295
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):
533559
# MISC #
534560
########
535561

562+
class Empty(object):
563+
pass
564+
536565
if sys.version_info < (2, 5):
537566
# Prior to Python 2.5, Exception was an old-style class
538567
def subclass_exception(name, parent, unused):

django/db/models/query.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def iterator(self):
153153
obj, _ = get_cached_row(self.model, row, index_start,
154154
max_depth, requested=requested)
155155
else:
156-
obj = self.model(*row[index_start:])
156+
obj = self.model.from_sequence(row[index_start:])
157157
for i, k in enumerate(extra_select):
158158
setattr(obj, k, row[i])
159159
yield obj
@@ -646,7 +646,7 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0,
646646

647647
restricted = requested is not None
648648
index_end = index_start + len(klass._meta.fields)
649-
obj = klass(*row[index_start:index_end])
649+
obj = klass.from_sequence(row[index_start:index_end])
650650
for f in klass._meta.fields:
651651
if (not f.rel or (not restricted and f.null) or
652652
(restricted and f.name not in requested) or f.rel.parent_link):

0 commit comments

Comments
 (0)