Django

Code

root/django/trunk/django/db/models/base.py

Revision 7814, 26.7 kB (checked in by jacob, 3 days ago)

Fixed #2070: refactored Django's file upload capabilities.

A description of the new features can be found in the new upload handling documentation; the executive summary is that Django will now happily handle uploads of large files without issues.

This changes the representation of uploaded files from dictionaries to bona fide objects; see BackwardsIncompatibleChanges for details.

  • Property svn:eol-style set to native
Line 
1 import copy
2 import types
3 import sys
4 import os
5 from itertools import izip
6
7 import django.db.models.manipulators    # Imported to register signal handler.
8 import django.db.models.manager         # Ditto.
9 from django.core import validators
10 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
11 from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist
12 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField
13 from django.db.models.query import delete_objects, Q, CollectedObjects
14 from django.db.models.options import Options, AdminOptions
15 from django.db import connection, transaction
16 from django.db.models import signals
17 from django.db.models.loading import register_models, get_model
18 from django.dispatch import dispatcher
19 from django.utils.datastructures import SortedDict
20 from django.utils.functional import curry
21 from django.utils.encoding import smart_str, force_unicode, smart_unicode
22 from django.core.files.move import file_move_safe
23 from django.core.files import locks
24 from django.conf import settings
25
26 try:
27     set
28 except NameError:
29     from sets import Set as set     # Python 2.3 fallback
30
31 class ModelBase(type):
32     "Metaclass for all models"
33     def __new__(cls, name, bases, attrs):
34         # If this isn't a subclass of Model, don't do anything special.
35         try:
36             parents = [b for b in bases if issubclass(b, Model)]
37         except NameError:
38             # 'Model' isn't defined yet, meaning we're looking at Django's own
39             # Model class, defined below.
40             parents = []
41         if not parents:
42             return super(ModelBase, cls).__new__(cls, name, bases, attrs)
43
44         # Create the class.
45         module = attrs.pop('__module__')
46         new_class = type.__new__(cls, name, bases, {'__module__': module})
47         attr_meta = attrs.pop('Meta', None)
48         abstract = getattr(attr_meta, 'abstract', False)
49         if not attr_meta:
50             meta = getattr(new_class, 'Meta', None)
51         else:
52             meta = attr_meta
53         base_meta = getattr(new_class, '_meta', None)
54
55         if getattr(meta, 'app_label', None) is None:
56             # Figure out the app_label by looking one level up.
57             # For 'django.contrib.sites.models', this would be 'sites'.
58             model_module = sys.modules[new_class.__module__]
59             kwargs = {"app_label": model_module.__name__.split('.')[-2]}
60         else:
61             kwargs = {}
62
63         new_class.add_to_class('_meta', Options(meta, **kwargs))
64         if not abstract:
65             new_class.add_to_class('DoesNotExist',
66                     subclass_exception('DoesNotExist', ObjectDoesNotExist, module))
67             new_class.add_to_class('MultipleObjectsReturned',
68                     subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module))
69             if base_meta and not base_meta.abstract:
70                 # Non-abstract child classes inherit some attributes from their
71                 # non-abstract parent (unless an ABC comes before it in the
72                 # method resolution order).
73                 if not hasattr(meta, 'ordering'):
74                     new_class._meta.ordering = base_meta.ordering
75                 if not hasattr(meta, 'get_latest_by'):
76                     new_class._meta.get_latest_by = base_meta.get_latest_by
77
78         old_default_mgr = None
79         if getattr(new_class, '_default_manager', None):
80             # We have a parent who set the default manager.
81             if new_class._default_manager.model._meta.abstract:
82                 old_default_mgr = new_class._default_manager
83             new_class._default_manager = None
84
85         # Bail out early if we have already created this class.
86         m = get_model(new_class._meta.app_label, name, False)
87         if m is not None:
88             return m
89
90         # Add all attributes to the class.
91         for obj_name, obj in attrs.items():
92             new_class.add_to_class(obj_name, obj)
93
94         # Do the appropriate setup for any model parents.
95         o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields
96                 if isinstance(f, OneToOneField)])
97         for base in parents:
98             if not hasattr(base, '_meta'):
99                 # Things without _meta aren't functional models, so they're
100                 # uninteresting parents.
101                 continue
102             if not base._meta.abstract:
103                 if base in o2o_map:
104                     field = o2o_map[base]
105                     field.primary_key = True
106                     new_class._meta.setup_pk(field)
107                 else:
108                     attr_name = '%s_ptr' % base._meta.module_name
109                     field = OneToOneField(base, name=attr_name,
110                             auto_created=True, parent_link=True)
111                     new_class.add_to_class(attr_name, field)
112                 new_class._meta.parents[base] = field
113             else:
114                 # The abstract base class case.
115                 names = set([f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many])
116                 for field in base._meta.local_fields + base._meta.local_many_to_many:
117                     if field.name in names:
118                         raise FieldError('Local field %r in class %r clashes with field of similar name from abstract base class %r'
119                                 % (field.name, name, base.__name__))
120                     new_class.add_to_class(field.name, copy.deepcopy(field))
121
122         if abstract:
123             # Abstract base models can't be instantiated and don't appear in
124             # the list of models for an app. We do the final setup for them a
125             # little differently from normal models.
126             attr_meta.abstract = False
127             new_class.Meta = attr_meta
128             return new_class
129
130         if old_default_mgr and not new_class._default_manager:
131             new_class._default_manager = old_default_mgr._copy_to_model(new_class)
132         new_class._prepare()
133         register_models(new_class._meta.app_label, new_class)
134
135         # Because of the way imports happen (recursively), we may or may not be
136         # the first time this model tries to register with the framework. There
137         # should only be one class for each model, so we always return the
138         # registered version.
139         return get_model(new_class._meta.app_label, name, False)
140
141     def add_to_class(cls, name, value):
142         if name == 'Admin':
143             assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
144             value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')]))
145         if hasattr(value, 'contribute_to_class'):
146             value.contribute_to_class(cls, name)
147         else:
148             setattr(cls, name, value)
149
150     def _prepare(cls):
151         # Creates some methods once self._meta has been populated.
152         opts = cls._meta
153         opts._prepare(cls)
154
155         if opts.order_with_respect_to:
156             cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
157             cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
158             setattr(opts.order_with_respect_to.rel.to, 'get_%s_order' % cls.__name__.lower(), curry(method_get_order, cls))
159             setattr(opts.order_with_respect_to.rel.to, 'set_%s_order' % cls.__name__.lower(), curry(method_set_order, cls))
160
161         # Give the class a docstring -- its definition.
162         if cls.__doc__ is None:
163             cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join([f.attname for f in opts.fields]))
164
165         if hasattr(cls, 'get_absolute_url'):
166             cls.get_absolute_url = curry(get_absolute_url, opts, cls.get_absolute_url)
167
168         dispatcher.send(signal=signals.class_prepared, sender=cls)
169
170 class Model(object):
171     __metaclass__ = ModelBase
172
173     def __init__(self, *args, **kwargs):
174         dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
175
176         # There is a rather weird disparity here; if kwargs, it's set, then args
177         # overrides it. It should be one or the other; don't duplicate the work
178         # The reason for the kwargs check is that standard iterator passes in by
179         # args, and instantiation for iteration is 33% faster.
180         args_len = len(args)
181         if args_len > len(self._meta.fields):
182             # Daft, but matches old exception sans the err msg.
183             raise IndexError("Number of args exceeds number of fields")
184
185         fields_iter = iter(self._meta.fields)
186         if not kwargs:
187             # The ordering of the izip calls matter - izip throws StopIteration
188             # when an iter throws it. So if the first iter throws it, the second
189             # is *not* consumed. We rely on this, so don't change the order
190             # without changing the logic.
191             for val, field in izip(args, fields_iter):
192                 setattr(self, field.attname, val)
193         else:
194             # Slower, kwargs-ready version.
195             for val, field in izip(args, fields_iter):
196                 setattr(self, field.attname, val)
197                 kwargs.pop(field.name, None)
198                 # Maintain compatibility with existing calls.
199                 if isinstance(field.rel, ManyToOneRel):
200                     kwargs.pop(field.attname, None)
201
202         # Now we're left with the unprocessed fields that *must* come from
203         # keywords, or default.
204
205         for field in fields_iter:
206             if kwargs:
207                 if isinstance(field.rel, ManyToOneRel):
208                     try:
209                         # Assume object instance was passed in.
210                         rel_obj = kwargs.pop(field.name)
211                     except KeyError:
212                         try:
213                             # Object instance wasn't passed in -- must be an ID.
214                             val = kwargs.pop(field.attname)
215                         except KeyError:
216                             val = field.get_default()
217                     else:
218                         # Object instance was passed in. Special case: You can
219                         # pass in "None" for related objects if it's allowed.
220                         if rel_obj is None and field.null:
221                             val = None
222                         else:
223                             try:
224                                 val = getattr(rel_obj, field.rel.get_related_field().attname)
225                             except AttributeError:
226                                 raise TypeError("Invalid value: %r should be a %s instance, not a %s" %
227                                     (field.name, field.rel.to, type(rel_obj)))
228                 else:
229                     val = kwargs.pop(field.attname, field.get_default())
230             else:
231                 val = field.get_default()
232             setattr(self, field.attname, val)
233
234         if kwargs:
235             for prop in kwargs.keys():
236                 try:
237                     if isinstance(getattr(self.__class__, prop), property):
238                         setattr(self, prop, kwargs.pop(prop))
239                 except AttributeError:
240                     pass
241             if kwargs:
242                 raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
243         dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
244
245     def __repr__(self):
246         return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))
247
248     def __str__(self):
249         if hasattr(self, '__unicode__'):
250             return force_unicode(self).encode('utf-8')
251         return '%s object' % self.__class__.__name__
252
253     def __eq__(self, other):
254         return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
255
256     def __ne__(self, other):
257         return not self.__eq__(other)
258
259     def __hash__(self):
260         return hash(self._get_pk_val())
261
262     def _get_pk_val(self, meta=None):
263         if not meta:
264             meta = self._meta
265         return getattr(self, meta.pk.attname)
266
267     def _set_pk_val(self, value):
268         return setattr(self, self._meta.pk.attname, value)
269
270     pk = property(_get_pk_val, _set_pk_val)
271
272     def save(self):
273         """
274         Save the current instance. Override this in a subclass if you want to
275         control the saving process.
276         """
277         self.save_base()
278
279     save.alters_data = True
280
281     def save_base(self, raw=False, cls=None):
282         """
283         Does the heavy-lifting involved in saving. Subclasses shouldn't need to
284         override this method. It's separate from save() in order to hide the
285         need for overrides of save() to pass around internal-only parameters
286         ('raw' and 'cls').
287         """
288         if not cls:
289             cls = self.__class__
290             meta = self._meta
291             signal = True
292             dispatcher.send(signal=signals.pre_save, sender=self.__class__,
293                     instance=self, raw=raw)
294         else:
295             meta = cls._meta
296             signal = False
297
298         # If we are in a raw save, save the object exactly as presented.
299         # That means that we don't try to be smart about saving attributes
300         # that might have come from the parent class - we just save the
301         # attributes we have been given to the class we have been given.
302         if not raw:
303             for parent, field in meta.parents.items():
304                 self.save_base(raw, parent)
305                 setattr(self, field.attname, self._get_pk_val(parent._meta))
306
307         non_pks = [f for f in meta.local_fields if not f.primary_key]
308            
309         # First, try an UPDATE. If that doesn't update anything, do an INSERT.
310         pk_val = self._get_pk_val(meta)
311         # Note: the comparison with '' is required for compatibility with
312         # oldforms-style model creation.
313         pk_set = pk_val is not None and smart_unicode(pk_val) != u''
314         record_exists = True
315         manager = cls._default_manager
316         if pk_set:
317             # Determine whether a record with the primary key already exists.
318             if manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by():
319                 # It does already exist, so do an UPDATE.
320                 if non_pks:
321                     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]
322                     manager.filter(pk=pk_val)._update(values)
323             else:
324                 record_exists = False
325         if not pk_set or not record_exists:
326             if not pk_set:
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 if not isinstance(f, AutoField)]
328             else:
329                 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]
330
331             if meta.order_with_respect_to:
332                 field = meta.order_with_respect_to
333                 values.append((meta.get_field_by_name('_order')[0], manager.filter(**{field.name: getattr(self, field.attname)}).count()))
334             record_exists = False
335
336             update_pk = bool(meta.has_auto_field and not pk_set)
337             if values:
338                 # Create a new record.
339                 result = manager._insert(values, return_id=update_pk)
340             else:
341                 # Create a new record with defaults for everything.
342                 result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True)
343
344             if update_pk:
345                 setattr(self, meta.pk.attname, result)
346         transaction.commit_unless_managed()
347
348         if signal:
349             dispatcher.send(signal=signals.post_save, sender=self.__class__,
350                     instance=self, created=(not record_exists), raw=raw)
351
352     save_base.alters_data = True
353
354     def validate(self):
355         """
356         First coerces all fields on this instance to their proper Python types.
357         Then runs validation on every field. Returns a dictionary of
358         field_name -> error_list.
359         """
360         error_dict = {}
361         invalid_python = {}
362         for f in self._meta.fields:
363             try:
364                 setattr(self, f.attname, f.to_python(getattr(self, f.attname, f.get_default())))
365             except validators.ValidationError, e:
366                 error_dict[f.name] = e.messages
367                 invalid_python[f.name] = 1
368         for f in self._meta.fields:
369             if f.name in invalid_python:
370                 continue
371             errors = f.validate_full(getattr(self, f.attname, f.get_default()), self.__dict__)
372             if errors:
373                 error_dict[f.name] = errors
374         return error_dict
375
376     def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
377         """
378         Recursively populates seen_objs with all objects related to this 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, ...}),...]
382         """
383         pk_val = self._get_pk_val()
384         if seen_objs.add(self.__class__, pk_val, self, parent, nullable):
385             return
386
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)
399
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)
414
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)
417
418         # Find all the objects than need to be deleted
419         seen_objs = CollectedObjects()
420         self._collect_sub_objects(seen_objs)
421
422         # Actually delete the objects
423         delete_objects(seen_objs)
424
425     delete.alters_data = True
426
427     def _get_FIELD_display(self, field):
428         value = getattr(self, field.attname)
429         return force_unicode(dict(field.choices).get(value, value), strings_only=True)
430
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
442
443     def _get_next_or_previous_in_order(self, is_next):
444         cachename