5 from itertools
import izip
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):
33 Metaclass for all models.
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
)]
39 # If this isn't a subclass of Model, don't do anything special.
40 return super_new(cls
, name
, bases
, attrs
)
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)
48 meta
= getattr(new_class
, 'Meta', None)
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]}
61 new_class
.add_to_class('_meta', Options(meta
, **kwargs
))
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)
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
)])
96 if not hasattr(base
, '_meta'):
97 # Things without _meta aren't functional models, so they're
98 # uninteresting parents.
100 if not base
._meta
.abstract
:
102 field
= o2o_map
[base
]
103 field
.primary_key
= True
104 new_class
._meta
.setup_pk(field
)
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
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
))
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
128 if old_default_mgr
and not new_class
._default
_manager
:
129 new_class
._default
_manager
= old_default_mgr
._copy
_to
_model
(new_class
)
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
)
143 setattr(cls
, name
, value
)
147 Creates some methods once self._meta has been populated.
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
)
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.
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
)
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
)
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
:
205 if isinstance(field
.rel
, ManyToOneRel
):
207 # Assume object instance was passed in.
208 rel_obj
= kwargs
.pop(field
.name
)
211 # Object instance wasn't passed in -- must be an ID.
212 val
= kwargs
.pop(field
.attname
)
214 val
= field
.get_default()
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
:
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
)))
227 val
= kwargs
.pop(field
.attname
, field
.get_default())
229 val
= field
.get_default()
230 setattr(self
, field
.attname
, val
)
233 for prop
in kwargs
.keys():
235 if isinstance(getattr(self
.__class
__, prop
), property):
236 setattr(self
, prop
, kwargs
.pop(prop
))
237 except AttributeError:
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
)
244 return smart_str(u
'<%s: %s>' % (self
.__class
__.__name
__, unicode(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
)
258 return hash(self
._get
_pk
_val
())
260 def _get_pk_val(self
, meta
=None):
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
)
272 Saves the current instance. Override this in a subclass if you want to
273 control the saving process.
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
290 dispatcher
.send(signal
=signals
.pre_save
, sender
=self
.__class
__,
291 instance
=self
, raw
=raw
)
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.
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
''
313 manager
= cls
._default
_manager
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.
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
)
322 record_exists
= False
323 if not pk_set
or not record_exists
:
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
)]
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
)
336 # Create a new record.
337 result
= manager
._insert
(values
, return_id
=update_pk
)
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)
343 setattr(self
, meta
.pk
.attname
, result
)
344 transaction
.commit_unless_managed()
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
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.
360 for f
in self
._meta
.fields
:
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
:
369 errors
= f
.validate_full(getattr(self
, f
.attname
, f
.get_default()), self
.__dict
__)
371 error_dict
[f
.name
] = errors
374 def _collect_sub_objects(self
, seen_objs
, parent
=None, nullable
=False):
376 Recursively populates seen_objs with all objects related to this
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
):
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
):
391 sub_obj
= getattr(self
, rel_opts_name
)
392 except ObjectDoesNotExist
:
395 sub_obj
._collect
_sub
_objects
(seen_objs
, self
.__class
__, related
.field
.null
)
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()
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())
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
)
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
)
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
))]
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
)))
465 def _get_FIELD_url(self
, field
):
466 if getattr(self
, field
.attname
): # Value is not blank.
468 return urlparse
.urljoin(settings
.MEDIA_URL
, getattr(self
, field
.attname
)).replace('\\', '/')
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.
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
484 if isinstance(raw_field
, dict):
487 message
= "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",
488 category
= DeprecationWarning,
491 from django
.core
.files
.uploadedfile
import SimpleUploadedFile
492 raw_field
= SimpleUploadedFile
.from_dict(raw_field
)
494 elif isinstance(raw_field
, basestring
):
497 message
= "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",
498 category
= DeprecationWarning,
501 from django
.core
.files
.uploadedfile
import SimpleUploadedFile
502 raw_field
= SimpleUploadedFile(filename
, raw_field
)
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
)):
513 dot_index
= filename
.rindex('.')
514 except ValueError: # filename has no dot.
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.
525 file_move_safe(raw_field
.temporary_file_path(), full_filename
)
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():
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.
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
)
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
,), {})
610 def subclass_exception(name
, parent
, module
):
611 return type(name
, (parent
,), {'__module__': module
})