Reverted [7986].
[django.git] / django / db / models / base.py
blob590aab97a4a136623d6e2b763bb3eed22cfc554c
1 import copy
2 import types
3 import sys
4 import os
5 from itertools import izip
6 try:
7 set
8 except NameError:
9 from sets import Set as set # Python 2.3 fallback.
11 import django.db.models.manipulators # Imported to register signal handler.
12 import django.db.models.manager # Ditto.
13 from django.core import validators
14 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
15 from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist
16 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField
17 from django.db.models.query import delete_objects, Q, CollectedObjects
18 from django.db.models.options import Options
19 from django.db import connection, transaction
20 from django.db.models import signals
21 from django.db.models.loading import register_models, get_model
22 from django.dispatch import dispatcher
23 from django.utils.datastructures import SortedDict
24 from django.utils.functional import curry
25 from django.utils.encoding import smart_str, force_unicode, smart_unicode
26 from django.core.files.move import file_move_safe
27 from django.core.files import locks
28 from django.conf import settings
31 class ModelBase(type):
32 """
33 Metaclass for all models.
34 """
35 def __new__(cls, name, bases, attrs):
36 super_new = super(ModelBase, cls).__new__
37 parents = [b for b in bases if isinstance(b, ModelBase)]
38 if not parents:
39 # If this isn't a subclass of Model, don't do anything special.
40 return super_new(cls, name, bases, attrs)
42 # Create the class.
43 module = attrs.pop('__module__')
44 new_class = super_new(cls, name, bases, {'__module__': module})
45 attr_meta = attrs.pop('Meta', None)
46 abstract = getattr(attr_meta, 'abstract', False)
47 if not attr_meta:
48 meta = getattr(new_class, 'Meta', None)
49 else:
50 meta = attr_meta
51 base_meta = getattr(new_class, '_meta', None)
53 if getattr(meta, 'app_label', None) is None:
54 # Figure out the app_label by looking one level up.
55 # For 'django.contrib.sites.models', this would be 'sites'.
56 model_module = sys.modules[new_class.__module__]
57 kwargs = {"app_label": model_module.__name__.split('.')[-2]}
58 else:
59 kwargs = {}
61 new_class.add_to_class('_meta', Options(meta, **kwargs))
62 if not abstract:
63 new_class.add_to_class('DoesNotExist',
64 subclass_exception('DoesNotExist', ObjectDoesNotExist, module))
65 new_class.add_to_class('MultipleObjectsReturned',
66 subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module))
67 if base_meta and not base_meta.abstract:
68 # Non-abstract child classes inherit some attributes from their
69 # non-abstract parent (unless an ABC comes before it in the
70 # method resolution order).
71 if not hasattr(meta, 'ordering'):
72 new_class._meta.ordering = base_meta.ordering
73 if not hasattr(meta, 'get_latest_by'):
74 new_class._meta.get_latest_by = base_meta.get_latest_by
76 old_default_mgr = None
77 if getattr(new_class, '_default_manager', None):
78 # We have a parent who set the default manager.
79 if new_class._default_manager.model._meta.abstract:
80 old_default_mgr = new_class._default_manager
81 new_class._default_manager = None
83 # Bail out early if we have already created this class.
84 m = get_model(new_class._meta.app_label, name, False)
85 if m is not None:
86 return m
88 # Add all attributes to the class.
89 for obj_name, obj in attrs.items():
90 new_class.add_to_class(obj_name, obj)
92 # Do the appropriate setup for any model parents.
93 o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields
94 if isinstance(f, OneToOneField)])
95 for base in parents:
96 if not hasattr(base, '_meta'):
97 # Things without _meta aren't functional models, so they're
98 # uninteresting parents.
99 continue
100 if not base._meta.abstract:
101 if base in o2o_map:
102 field = o2o_map[base]
103 field.primary_key = True
104 new_class._meta.setup_pk(field)
105 else:
106 attr_name = '%s_ptr' % base._meta.module_name
107 field = OneToOneField(base, name=attr_name,
108 auto_created=True, parent_link=True)
109 new_class.add_to_class(attr_name, field)
110 new_class._meta.parents[base] = field
111 else:
112 # The abstract base class case.
113 names = set([f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many])
114 for field in base._meta.local_fields + base._meta.local_many_to_many:
115 if field.name in names:
116 raise FieldError('Local field %r in class %r clashes with field of similar name from abstract base class %r'
117 % (field.name, name, base.__name__))
118 new_class.add_to_class(field.name, copy.deepcopy(field))
120 if abstract:
121 # Abstract base models can't be instantiated and don't appear in
122 # the list of models for an app. We do the final setup for them a
123 # little differently from normal models.
124 attr_meta.abstract = False
125 new_class.Meta = attr_meta
126 return new_class
128 if old_default_mgr and not new_class._default_manager:
129 new_class._default_manager = old_default_mgr._copy_to_model(new_class)
130 new_class._prepare()
131 register_models(new_class._meta.app_label, new_class)
133 # Because of the way imports happen (recursively), we may or may not be
134 # the first time this model tries to register with the framework. There
135 # should only be one class for each model, so we always return the
136 # registered version.
137 return get_model(new_class._meta.app_label, name, False)
139 def add_to_class(cls, name, value):
140 if hasattr(value, 'contribute_to_class'):
141 value.contribute_to_class(cls, name)
142 else:
143 setattr(cls, name, value)
145 def _prepare(cls):
147 Creates some methods once self._meta has been populated.
149 opts = cls._meta
150 opts._prepare(cls)
152 if opts.order_with_respect_to:
153 cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
154 cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
155 setattr(opts.order_with_respect_to.rel.to, 'get_%s_order' % cls.__name__.lower(), curry(method_get_order, cls))
156 setattr(opts.order_with_respect_to.rel.to, 'set_%s_order' % cls.__name__.lower(), curry(method_set_order, cls))
158 # Give the class a docstring -- its definition.
159 if cls.__doc__ is None:
160 cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join([f.attname for f in opts.fields]))
162 if hasattr(cls, 'get_absolute_url'):
163 cls.get_absolute_url = curry(get_absolute_url, opts, cls.get_absolute_url)
165 dispatcher.send(signal=signals.class_prepared, sender=cls)
168 class Model(object):
169 __metaclass__ = ModelBase
171 def __init__(self, *args, **kwargs):
172 dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
174 # There is a rather weird disparity here; if kwargs, it's set, then args
175 # overrides it. It should be one or the other; don't duplicate the work
176 # The reason for the kwargs check is that standard iterator passes in by
177 # args, and instantiation for iteration is 33% faster.
178 args_len = len(args)
179 if args_len > len(self._meta.fields):
180 # Daft, but matches old exception sans the err msg.
181 raise IndexError("Number of args exceeds number of fields")
183 fields_iter = iter(self._meta.fields)
184 if not kwargs:
185 # The ordering of the izip calls matter - izip throws StopIteration
186 # when an iter throws it. So if the first iter throws it, the second
187 # is *not* consumed. We rely on this, so don't change the order
188 # without changing the logic.
189 for val, field in izip(args, fields_iter):
190 setattr(self, field.attname, val)
191 else:
192 # Slower, kwargs-ready version.
193 for val, field in izip(args, fields_iter):
194 setattr(self, field.attname, val)
195 kwargs.pop(field.name, None)
196 # Maintain compatibility with existing calls.
197 if isinstance(field.rel, ManyToOneRel):
198 kwargs.pop(field.attname, None)
200 # Now we're left with the unprocessed fields that *must* come from
201 # keywords, or default.
203 for field in fields_iter:
204 if kwargs:
205 if isinstance(field.rel, ManyToOneRel):
206 try:
207 # Assume object instance was passed in.
208 rel_obj = kwargs.pop(field.name)
209 except KeyError:
210 try:
211 # Object instance wasn't passed in -- must be an ID.
212 val = kwargs.pop(field.attname)
213 except KeyError:
214 val = field.get_default()
215 else:
216 # Object instance was passed in. Special case: You can
217 # pass in "None" for related objects if it's allowed.
218 if rel_obj is None and field.null:
219 val = None
220 else:
221 try:
222 val = getattr(rel_obj, field.rel.get_related_field().attname)
223 except AttributeError:
224 raise TypeError("Invalid value: %r should be a %s instance, not a %s" %
225 (field.name, field.rel.to, type(rel_obj)))
226 else:
227 val = kwargs.pop(field.attname, field.get_default())
228 else:
229 val = field.get_default()
230 setattr(self, field.attname, val)
232 if kwargs:
233 for prop in kwargs.keys():
234 try:
235 if isinstance(getattr(self.__class__, prop), property):
236 setattr(self, prop, kwargs.pop(prop))
237 except AttributeError:
238 pass
239 if kwargs:
240 raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
241 dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
243 def __repr__(self):
244 return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))
246 def __str__(self):
247 if hasattr(self, '__unicode__'):
248 return force_unicode(self).encode('utf-8')
249 return '%s object' % self.__class__.__name__
251 def __eq__(self, other):
252 return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
254 def __ne__(self, other):
255 return not self.__eq__(other)
257 def __hash__(self):
258 return hash(self._get_pk_val())
260 def _get_pk_val(self, meta=None):
261 if not meta:
262 meta = self._meta
263 return getattr(self, meta.pk.attname)
265 def _set_pk_val(self, value):
266 return setattr(self, self._meta.pk.attname, value)
268 pk = property(_get_pk_val, _set_pk_val)
270 def save(self):
272 Saves the current instance. Override this in a subclass if you want to
273 control the saving process.
275 self.save_base()
277 save.alters_data = True
279 def save_base(self, raw=False, cls=None):
281 Does the heavy-lifting involved in saving. Subclasses shouldn't need to
282 override this method. It's separate from save() in order to hide the
283 need for overrides of save() to pass around internal-only parameters
284 ('raw' and 'cls').
286 if not cls:
287 cls = self.__class__
288 meta = self._meta
289 signal = True
290 dispatcher.send(signal=signals.pre_save, sender=self.__class__,
291 instance=self, raw=raw)
292 else:
293 meta = cls._meta
294 signal = False
296 # If we are in a raw save, save the object exactly as presented.
297 # That means that we don't try to be smart about saving attributes
298 # that might have come from the parent class - we just save the
299 # attributes we have been given to the class we have been given.
300 if not raw:
301 for parent, field in meta.parents.items():
302 self.save_base(raw, parent)
303 setattr(self, field.attname, self._get_pk_val(parent._meta))
305 non_pks = [f for f in meta.local_fields if not f.primary_key]
307 # First, try an UPDATE. If that doesn't update anything, do an INSERT.
308 pk_val = self._get_pk_val(meta)
309 # Note: the comparison with '' is required for compatibility with
310 # oldforms-style model creation.
311 pk_set = pk_val is not None and smart_unicode(pk_val) != u''
312 record_exists = True
313 manager = cls._default_manager
314 if pk_set:
315 # Determine whether a record with the primary key already exists.
316 if manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by():
317 # It does already exist, so do an UPDATE.
318 if non_pks:
319 values = [(f, None, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
320 manager.filter(pk=pk_val)._update(values)
321 else:
322 record_exists = False
323 if not pk_set or not record_exists:
324 if not pk_set:
325 values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)]
326 else:
327 values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields]
329 if meta.order_with_respect_to:
330 field = meta.order_with_respect_to
331 values.append((meta.get_field_by_name('_order')[0], manager.filter(**{field.name: getattr(self, field.attname)}).count()))
332 record_exists = False
334 update_pk = bool(meta.has_auto_field and not pk_set)
335 if values:
336 # Create a new record.
337 result = manager._insert(values, return_id=update_pk)
338 else:
339 # Create a new record with defaults for everything.
340 result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True)
342 if update_pk:
343 setattr(self, meta.pk.attname, result)
344 transaction.commit_unless_managed()
346 if signal:
347 dispatcher.send(signal=signals.post_save, sender=self.__class__,
348 instance=self, created=(not record_exists), raw=raw)
350 save_base.alters_data = True
352 def validate(self):
354 First coerces all fields on this instance to their proper Python types.
355 Then runs validation on every field. Returns a dictionary of
356 field_name -> error_list.
358 error_dict = {}
359 invalid_python = {}
360 for f in self._meta.fields:
361 try:
362 setattr(self, f.attname, f.to_python(getattr(self, f.attname, f.get_default())))
363 except validators.ValidationError, e:
364 error_dict[f.name] = e.messages
365 invalid_python[f.name] = 1
366 for f in self._meta.fields:
367 if f.name in invalid_python:
368 continue
369 errors = f.validate_full(getattr(self, f.attname, f.get_default()), self.__dict__)
370 if errors:
371 error_dict[f.name] = errors
372 return error_dict
374 def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
376 Recursively populates seen_objs with all objects related to this
377 object.
379 When done, seen_objs.items() will be in the format:
380 [(model_class, {pk_val: obj, pk_val: obj, ...}),
381 (model_class, {pk_val: obj, pk_val: obj, ...}), ...]
383 pk_val = self._get_pk_val()
384 if seen_objs.add(self.__class__, pk_val, self, parent, nullable):
385 return
387 for related in self._meta.get_all_related_objects():
388 rel_opts_name = related.get_accessor_name()
389 if isinstance(related.field.rel, OneToOneRel):
390 try:
391 sub_obj = getattr(self, rel_opts_name)
392 except ObjectDoesNotExist:
393 pass
394 else:
395 sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
396 else:
397 for sub_obj in getattr(self, rel_opts_name).all():
398 sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
400 # Handle any ancestors (for the model-inheritance case). We do this by
401 # traversing to the most remote parent classes -- those with no parents
402 # themselves -- and then adding those instances to the collection. That
403 # will include all the child instances down to "self".
404 parent_stack = self._meta.parents.values()
405 while parent_stack:
406 link = parent_stack.pop()
407 parent_obj = getattr(self, link.name)
408 if parent_obj._meta.parents:
409 parent_stack.extend(parent_obj._meta.parents.values())
410 continue
411 # At this point, parent_obj is base class (no ancestor models). So
412 # delete it and all its descendents.
413 parent_obj._collect_sub_objects(seen_objs)
415 def delete(self):
416 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)
418 # Find all the objects than need to be deleted.
419 seen_objs = CollectedObjects()
420 self._collect_sub_objects(seen_objs)
422 # Actually delete the objects.
423 delete_objects(seen_objs)
425 delete.alters_data = True
427 def _get_FIELD_display(self, field):
428 value = getattr(self, field.attname)
429 return force_unicode(dict(field.flatchoices).get(value, value), strings_only=True)
431 def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
432 op = is_next and 'gt' or 'lt'
433 order = not is_next and '-' or ''
434 param = smart_str(getattr(self, field.attname))
435 q = Q(**{'%s__%s' % (field.name, op): param})
436 q = q|Q(**{field.name: param, 'pk__%s' % op: self.pk})
437 qs = self.__class__._default_manager.filter(**kwargs).filter(q).order_by('%s%s' % (order, field.name), '%spk' % order)
438 try:
439 return qs[0]
440 except IndexError:
441 raise self.DoesNotExist, "%s matching query does not exist." % self.__class__._meta.object_name
443 def _get_next_or_previous_in_order(self, is_next):
444 cachename = "__%s_order_cache" % is_next
445 if not hasattr(self, cachename):
446 qn = connection.ops.quote_name
447 op = is_next and '>' or '<'
448 order = not is_next and '-_order' or '_order'
449 order_field = self._meta.order_with_respect_to
450 # FIXME: When querysets support nested queries, this can be turned
451 # into a pure queryset operation.
452 where = ['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \
453 (qn('_order'), op, qn('_order'),
454 qn(self._meta.db_table), qn(self._meta.pk.column))]
455 params = [self.pk]
456 obj = self._default_manager.filter(**{order_field.name: getattr(self, order_field.attname)}).extra(where=where, params=params).order_by(order)[:1].get()
457 setattr(self, cachename, obj)
458 return getattr(self, cachename)
460 def _get_FIELD_filename(self, field):
461 if getattr(self, field.attname): # Value is not blank.
462 return os.path.normpath(os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname)))
463 return ''
465 def _get_FIELD_url(self, field):
466 if getattr(self, field.attname): # Value is not blank.
467 import urlparse
468 return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/')
469 return ''
471 def _get_FIELD_size(self, field):
472 return os.path.getsize(self._get_FIELD_filename(field))
474 def _save_FIELD_file(self, field, filename, raw_field, save=True):
475 directory = field.get_directory_name()
476 try: # Create the date-based directory if it doesn't exist.
477 os.makedirs(os.path.join(settings.MEDIA_ROOT, directory))
478 except OSError: # Directory probably already exists.
479 pass
481 # Check for old-style usage (files-as-dictionaries). Warn here first
482 # since there are multiple locations where we need to support both new
483 # and old usage.
484 if isinstance(raw_field, dict):
485 import warnings
486 warnings.warn(
487 message = "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",
488 category = DeprecationWarning,
489 stacklevel = 2
491 from django.core.files.uploadedfile import SimpleUploadedFile
492 raw_field = SimpleUploadedFile.from_dict(raw_field)
494 elif isinstance(raw_field, basestring):
495 import warnings
496 warnings.warn(
497 message = "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",
498 category = DeprecationWarning,
499 stacklevel = 2
501 from django.core.files.uploadedfile import SimpleUploadedFile
502 raw_field = SimpleUploadedFile(filename, raw_field)
504 if filename is None:
505 filename = raw_field.file_name
507 filename = field.get_filename(filename)
509 # If the filename already exists, keep adding an underscore to the name
510 # of the file until the filename doesn't exist.
511 while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):
512 try:
513 dot_index = filename.rindex('.')
514 except ValueError: # filename has no dot.
515 filename += '_'
516 else:
517 filename = filename[:dot_index] + '_' + filename[dot_index:]
519 # Save the file name on the object and write the file to disk.
520 setattr(self, field.attname, filename)
521 full_filename = self._get_FIELD_filename(field)
522 if hasattr(raw_field, 'temporary_file_path'):
523 # This file has a file path that we can move.
524 raw_field.close()
525 file_move_safe(raw_field.temporary_file_path(), full_filename)
526 else:
527 # This is a normal uploadedfile that we can stream.
528 fp = open(full_filename, 'wb')
529 locks.lock(fp, locks.LOCK_EX)
530 for chunk in raw_field.chunks():
531 fp.write(chunk)
532 locks.unlock(fp)
533 fp.close()
535 # Save the width and/or height, if applicable.
536 if isinstance(field, ImageField) and \
537 (field.width_field or field.height_field):
538 from django.utils.images import get_image_dimensions
539 width, height = get_image_dimensions(full_filename)
540 if field.width_field:
541 setattr(self, field.width_field, width)
542 if field.height_field:
543 setattr(self, field.height_field, height)
545 # Save the object because it has changed, unless save is False.
546 if save:
547 self.save()
549 _save_FIELD_file.alters_data = True
551 def _get_FIELD_width(self, field):
552 return self._get_image_dimensions(field)[0]
554 def _get_FIELD_height(self, field):
555 return self._get_image_dimensions(field)[1]
557 def _get_image_dimensions(self, field):
558 cachename = "__%s_dimensions_cache" % field.name
559 if not hasattr(self, cachename):
560 from django.utils.images import get_image_dimensions
561 filename = self._get_FIELD_filename(field)
562 setattr(self, cachename, get_image_dimensions(filename))
563 return getattr(self, cachename)
566 ############################################
567 # HELPER FUNCTIONS (CURRIED MODEL METHODS) #
568 ############################################
570 # ORDERING METHODS #########################
572 def method_set_order(ordered_obj, self, id_list):
573 rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
574 order_name = ordered_obj._meta.order_with_respect_to.name
575 # FIXME: It would be nice if there was an "update many" version of update
576 # for situations like this.
577 for i, j in enumerate(id_list):
578 ordered_obj.objects.filter(**{'pk': j, order_name: rel_val}).update(_order=i)
579 transaction.commit_unless_managed()
582 def method_get_order(ordered_obj, self):
583 rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
584 order_name = ordered_obj._meta.order_with_respect_to.name
585 pk_name = ordered_obj._meta.pk.name
586 return [r[pk_name] for r in
587 ordered_obj.objects.filter(**{order_name: rel_val}).values(pk_name)]
590 ##############################################
591 # HELPER FUNCTIONS (CURRIED MODEL FUNCTIONS) #
592 ##############################################
594 def get_absolute_url(opts, func, self, *args, **kwargs):
595 return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self, *args, **kwargs)
598 ########
599 # MISC #
600 ########
602 class Empty(object):
603 pass
605 if sys.version_info < (2, 5):
606 # Prior to Python 2.5, Exception was an old-style class
607 def subclass_exception(name, parent, unused):
608 return types.ClassType(name, (parent,), {})
609 else:
610 def subclass_exception(name, parent, module):
611 return type(name, (parent,), {'__module__': module})