magic-removal: Merged to [1717]

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1718 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2005-12-17 19:35:04 +00:00
parent bb874b690a
commit 06332287a8
4 changed files with 60 additions and 65 deletions

View File

@ -121,9 +121,6 @@ def cmp_cls(x, y):
return 1 return 1
return 0 return 0
class Model(object): class Model(object):
__metaclass__ = ModelBase __metaclass__ = ModelBase
@ -134,7 +131,6 @@ class Model(object):
setattr(cls, name, attribute) setattr(cls, name, attribute)
add_to_class = classmethod(add_to_class) add_to_class = classmethod(add_to_class)
def __repr__(self): def __repr__(self):
return '<%s object>' % self.__class__.__name__ return '<%s object>' % self.__class__.__name__
@ -181,7 +177,7 @@ class Model(object):
def _prepare(cls): def _prepare(cls):
cls.add_to_class( 'AddManipulator', ModelAddManipulator) cls.add_to_class( 'AddManipulator', ModelAddManipulator)
cls.add_to_class( 'ChangeManipulator', ModelChangeManipulator) cls.add_to_class( 'ChangeManipulator', ModelChangeManipulator)
# Creates some methods once self._meta has been populated. # Creates some methods once self._meta has been populated.
if cls._meta.order_with_respect_to: if cls._meta.order_with_respect_to:
@ -244,7 +240,7 @@ class Model(object):
# Run any post-save hooks. # Run any post-save hooks.
dispatcher.send(signal=Signals.pre_save, sender = self.__class__, instance = self ) dispatcher.send(signal=Signals.pre_save, sender = self.__class__, instance = self )
if hasattr(self, '_post_save'): if hasattr(self, '_post_save'):
self._post_save() self._post_save()
@ -297,7 +293,7 @@ class Model(object):
# Run any pre-delete hooks. # Run any pre-delete hooks.
if hasattr(instance, '_pre_delete'): if hasattr(instance, '_pre_delete'):
instance._pre_delete() instance._pre_delete()
dispatcher.send(signal=Signals.pre_delete, sender = cls, instance = instance ) dispatcher.send(signal=Signals.pre_delete, sender = cls, instance = instance )
for related in cls._meta.get_all_related_many_to_many_objects(): for related in cls._meta.get_all_related_many_to_many_objects():
@ -327,9 +323,9 @@ class Model(object):
[pk_val]) [pk_val])
setattr(self, cls._meta.pk.attname, None) setattr(self, cls._meta.pk.attname, None)
dispatcher.send(signal=Signals.post_delete, sender = cls, instance = instance ) dispatcher.send(signal=Signals.post_delete, sender = cls, instance = instance )
if hasattr(instance, '_post_delete'): if hasattr(instance, '_post_delete'):
instance._post_delete() instance._post_delete()

View File

@ -36,8 +36,8 @@ def manipulator_valid_rel_key(f, self, field_data, all_data):
def manipulator_validator_unique(f, opts, self, field_data, all_data): def manipulator_validator_unique(f, opts, self, field_data, all_data):
"Validates that the value is unique for this field." "Validates that the value is unique for this field."
lookup_type = f.get_validator_unique_lookup_type() lookup_type = f.get_validator_unique_lookup_type()
try: try:
old_obj = self.__class__._default_manager.get_object(**{lookup_type: field_data}) old_obj = self.__class__._default_manager.get_object(**{lookup_type: field_data})
except ObjectDoesNotExist: except ObjectDoesNotExist:
@ -88,7 +88,7 @@ class Field(object):
# Tracks each time a Field instance is created. Used to retain order. # Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0 creation_counter = 0
def __init__(self, verbose_name=None, name=None, primary_key=False, def __init__(self, verbose_name=None, name=None, primary_key=False,
maxlength=None, unique=False, blank=False, null=False, db_index=False, maxlength=None, unique=False, blank=False, null=False, db_index=False,
core=False, rel=None, default=NOT_PROVIDED, editable=True, core=False, rel=None, default=NOT_PROVIDED, editable=True,
@ -96,8 +96,8 @@ class Field(object):
unique_for_year=None, validator_list=None, choices=None, radio_admin=None, unique_for_year=None, validator_list=None, choices=None, radio_admin=None,
help_text='', db_column=None): help_text='', db_column=None):
self.name = name self.name = name
self.verbose_name = verbose_name self.verbose_name = verbose_name
self.primary_key = primary_key self.primary_key = primary_key
self.maxlength, self.unique = maxlength, unique self.maxlength, self.unique = maxlength, unique
self.blank, self.null = blank, null self.blank, self.null = blank, null
@ -111,7 +111,7 @@ class Field(object):
self.radio_admin = radio_admin self.radio_admin = radio_admin
self.help_text = help_text self.help_text = help_text
self.db_column = db_column self.db_column = db_column
# Set db_index to True if the field has a relationship and doesn't explicitly set db_index. # Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
self.db_index = db_index self.db_index = db_index
# Increase the creation counter, and save our local copy. # Increase the creation counter, and save our local copy.
@ -120,7 +120,7 @@ class Field(object):
def __cmp__(self,other ): def __cmp__(self,other ):
#This is because bisect does not take a comparison function. grrr. #This is because bisect does not take a comparison function. grrr.
return cmp(self.creation_counter, other.creation_counter) return cmp(self.creation_counter, other.creation_counter)
def set_attributes_from_name(self, name): def set_attributes_from_name(self, name):
@ -205,7 +205,7 @@ class Field(object):
params = {'validator_list': self.validator_list[:]} params = {'validator_list': self.validator_list[:]}
if self.maxlength and not self.choices: # Don't give SelectFields a maxlength parameter. if self.maxlength and not self.choices: # Don't give SelectFields a maxlength parameter.
params['maxlength'] = self.maxlength params['maxlength'] = self.maxlength
if self.choices: if self.choices:
if self.radio_admin: if self.radio_admin:
field_objs = [formfields.RadioSelectField] field_objs = [formfields.RadioSelectField]
@ -292,7 +292,7 @@ class Field(object):
first_choice = include_blank and blank_choice or [] first_choice = include_blank and blank_choice or []
if self.choices: if self.choices:
return first_choice + list(self.choices) return first_choice + list(self.choices)
rel_model = self.rel.to rel_model = self.rel.to
return first_choice + [(getattr(x, rel_model._meta.pk.attname), str(x)) return first_choice + [(getattr(x, rel_model._meta.pk.attname), str(x))
for x in rel_model._default_manager.get_list(**rel_model._meta.limit_choices_to)] for x in rel_model._default_manager.get_list(**rel_model._meta.limit_choices_to)]
@ -386,10 +386,10 @@ class DateField(Field):
def contribute_to_class(self,cls, name ): def contribute_to_class(self,cls, name ):
super(DateField,self).contribute_to_class(cls, name) super(DateField,self).contribute_to_class(cls, name)
if not self.null: if not self.null:
setattr(cls, 'get_next_by_%s' % self.name, setattr(cls, 'get_next_by_%s' % self.name,
curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=True)) curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=True))
setattr(cls, 'get_previous_by_%s' % self.name, setattr(cls, 'get_previous_by_%s' % self.name,
curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False)) curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False))
# Needed because of horrible auto_now[_add] behaviour wrt. editable # Needed because of horrible auto_now[_add] behaviour wrt. editable
def get_follow(self, override=None): def get_follow(self, override=None):
@ -510,7 +510,7 @@ class FileField(Field):
signal = Signals.post_delete, signal = Signals.post_delete,
sender = cls sender = cls
) )
def delete_file(self, instance): def delete_file(self, instance):
if getattr(instance, f.attname): if getattr(instance, f.attname):
file_name = getattr(instance, 'get_%s_filename' % f.name)() file_name = getattr(instance, 'get_%s_filename' % f.name)()
@ -570,9 +570,8 @@ class ImageField(FileField):
def contribute_to_class(self, cls, name): def contribute_to_class(self, cls, name):
super(FileField, self).contribute_to_class(cls, name) super(FileField, self).contribute_to_class(cls, name)
# Add get_BLAH_width and get_BLAH_height methods, but only # Add get_BLAH_width and get_BLAH_height methods, but only if the
# if the image field doesn't have width and height cache # image field doesn't have width and height cache fields.
# fields.
if not self.width_field: if not self.width_field:
setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self)) setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))
if not self.height_field: if not self.height_field:

View File

@ -5,7 +5,7 @@ from django.db.models.fields import FileField, AutoField
class ManipulatorDescriptor(object): class ManipulatorDescriptor(object):
class empty: class empty:
pass pass
def __init__(self, name, base): def __init__(self, name, base):
self.man = None self.man = None
self.name = name self.name = name
@ -18,12 +18,12 @@ class ManipulatorDescriptor(object):
if not self.man: if not self.man:
class Man(self.get_base_manipulator(type), self.base): class Man(self.get_base_manipulator(type), self.base):
pass pass
Man._prepare(type) Man._prepare(type)
Man.__name__ = self.name Man.__name__ = self.name
self.man = Man self.man = Man
return self.man return self.man
def get_base_manipulator(self, type): def get_base_manipulator(self, type):
if hasattr(type, 'MANIPULATOR'): if hasattr(type, 'MANIPULATOR'):
man = type.MANIPULATOR man = type.MANIPULATOR
@ -47,11 +47,11 @@ class AutomaticManipulator(Manipulator):
if f.unique_for_year: if f.unique_for_year:
setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_year), curry(manipulator_validator_unique_for_date, f, opts.get_field(f.unique_for_year), opts, 'year')) setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_year), curry(manipulator_validator_unique_for_date, f, opts.get_field(f.unique_for_year), opts, 'year'))
_prepare = classmethod(_prepare) _prepare = classmethod(_prepare)
def contribute_to_class(cls, other_cls, name ): def contribute_to_class(cls, other_cls, name ):
setattr(other_cls, name, ManipulatorDescriptor(name, cls)) setattr(other_cls, name, ManipulatorDescriptor(name, cls))
contribute_to_class = classmethod(contribute_to_class) contribute_to_class = classmethod(contribute_to_class)
def __init__(self, original_object= None, follow=None): def __init__(self, original_object= None, follow=None):
self.follow = self.model._meta.get_follow(follow) self.follow = self.model._meta.get_follow(follow)
self.fields = [] self.fields = []
@ -59,8 +59,8 @@ class AutomaticManipulator(Manipulator):
for f in self.opts.fields + self.opts.many_to_many: for f in self.opts.fields + self.opts.many_to_many:
if self.follow.get(f.name, False): if self.follow.get(f.name, False):
self.fields.extend(f.get_manipulator_fields(self.opts, self, self.change)) self.fields.extend(f.get_manipulator_fields(self.opts, self, self.change))
# Add fields for related objects. # Add fields for related objects.
for f in self.opts.get_all_related_objects(): for f in self.opts.get_all_related_objects():
if self.follow.get(f.name, False): if self.follow.get(f.name, False):
@ -69,8 +69,8 @@ class AutomaticManipulator(Manipulator):
fields = f.get_manipulator_fields(self.opts, self, self.change, fol) fields = f.get_manipulator_fields(self.opts, self, self.change, fol)
print fields print fields
self.fields.extend(fields) self.fields.extend(fields)
def save(self, new_data): def save(self, new_data):
add, change, opts, klass = self.add, self.change, self.opts, self.model add, change, opts, klass = self.add, self.change, self.opts, self.model
# TODO: big cleanup when core fields go -> use recursive manipulators. # TODO: big cleanup when core fields go -> use recursive manipulators.
@ -87,26 +87,26 @@ class AutomaticManipulator(Manipulator):
else: else:
param = f.get_default() param = f.get_default()
params[f.attname] = param params[f.attname] = param
if change: if change:
params[opts.pk.attname] = self.obj_key params[opts.pk.attname] = self.obj_key
# First, save the basic object itself. # First, save the basic object itself.
new_object = klass(**params) new_object = klass(**params)
new_object.save() new_object.save()
# Now that the object's been saved, save any uploaded files. # Now that the object's been saved, save any uploaded files.
for f in opts.fields: for f in opts.fields:
if isinstance(f, FileField): if isinstance(f, FileField):
f.save_file(new_data, new_object, change and self.original_object or None, change, rel=False) f.save_file(new_data, new_object, change and self.original_object or None, change, rel=False)
# Calculate which primary fields have changed. # Calculate which primary fields have changed.
if change: if change:
self.fields_added, self.fields_changed, self.fields_deleted = [], [], [] self.fields_added, self.fields_changed, self.fields_deleted = [], [], []
for f in opts.fields: for f in opts.fields:
if not f.primary_key and str(getattr(self.original_object, f.attname)) != str(getattr(new_object, f.attname)): if not f.primary_key and str(getattr(self.original_object, f.attname)) != str(getattr(new_object, f.attname)):
self.fields_changed.append(f.verbose_name) self.fields_changed.append(f.verbose_name)
# Save many-to-many objects. Example: Poll.set_sites() # Save many-to-many objects. Example: Poll.set_sites()
for f in opts.many_to_many: for f in opts.many_to_many:
if self.follow.get(f.name, None): if self.follow.get(f.name, None):
@ -118,7 +118,7 @@ class AutomaticManipulator(Manipulator):
was_changed = getattr(new_object, 'set_%s' % f.name)(new_vals) was_changed = getattr(new_object, 'set_%s' % f.name)(new_vals)
if change and was_changed: if change and was_changed:
self.fields_changed.append(f.verbose_name) self.fields_changed.append(f.verbose_name)
expanded_data = DotExpandedDict(dict(new_data)) expanded_data = DotExpandedDict(dict(new_data))
# Save many-to-one objects. Example: Add the Choice objects for a Poll. # Save many-to-one objects. Example: Add the Choice objects for a Poll.
for related in opts.get_all_related_objects(): for related in opts.get_all_related_objects():
@ -127,22 +127,23 @@ class AutomaticManipulator(Manipulator):
# ('1', {'id': ['941'], 'choice': ['This is the second choice']}), # ('1', {'id': ['941'], 'choice': ['This is the second choice']}),
# ('2', {'id': [''], 'choice': ['']})] # ('2', {'id': [''], 'choice': ['']})]
child_follow = self.follow.get(related.name, None) child_follow = self.follow.get(related.name, None)
if child_follow: if child_follow:
obj_list = expanded_data[related.var_name].items() obj_list = expanded_data[related.var_name].items()
obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0]))) obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0])))
params = {}
# For each related item... # For each related item...
for _, rel_new_data in obj_list: for _, rel_new_data in obj_list:
params = {}
# Keep track of which core=True fields were provided. # Keep track of which core=True fields were provided.
# If all core fields were given, the related object will be saved. # If all core fields were given, the related object will be saved.
# If none of the core fields were given, the object will be deleted. # If none of the core fields were given, the object will be deleted.
# If some, but not all, of the fields were given, the validator would # If some, but not all, of the fields were given, the validator would
# have caught that. # have caught that.
all_cores_given, all_cores_blank = True, True all_cores_given, all_cores_blank = True, True
# Get a reference to the old object. We'll use it to compare the # Get a reference to the old object. We'll use it to compare the
# old to the new, to see which fields have changed. # old to the new, to see which fields have changed.
old_rel_obj = None old_rel_obj = None
@ -152,7 +153,7 @@ class AutomaticManipulator(Manipulator):
old_rel_obj = getattr(self.original_object, 'get_%s' % related.get_method_name_part() )(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.attname][0]}) old_rel_obj = getattr(self.original_object, 'get_%s' % related.get_method_name_part() )(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.attname][0]})
except ObjectDoesNotExist: except ObjectDoesNotExist:
pass pass
for f in related.opts.fields: for f in related.opts.fields:
if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''): if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''):
all_cores_given = False all_cores_given = False
@ -162,7 +163,7 @@ class AutomaticManipulator(Manipulator):
# previously, according to the given ID. If the ID wasn't # previously, according to the given ID. If the ID wasn't
# given, use a default value. FileFields are also a special # given, use a default value. FileFields are also a special
# case, because they'll be dealt with later. # case, because they'll be dealt with later.
if f == related.field: if f == related.field:
param = getattr(new_object, related.field.rel.field_name) param = getattr(new_object, related.field.rel.field_name)
elif add and isinstance(f, AutoField): elif add and isinstance(f, AutoField):
@ -176,20 +177,20 @@ class AutomaticManipulator(Manipulator):
param = f.get_manipulator_new_data(rel_new_data, rel=True) param = f.get_manipulator_new_data(rel_new_data, rel=True)
if param != None: if param != None:
params[f.attname] = param params[f.attname] = param
# Create the related item. # Create the related item.
new_rel_obj = related.model(**params) new_rel_obj = related.model(**params)
# If all the core fields were provided (non-empty), save the item. # If all the core fields were provided (non-empty), save the item.
if all_cores_given: if all_cores_given:
new_rel_obj.save() new_rel_obj.save()
# Save any uploaded files. # Save any uploaded files.
for f in related.opts.fields: for f in related.opts.fields:
if child_follow.get(f.name, None): if child_follow.get(f.name, None):
if isinstance(f, FileField) and rel_new_data.get(f.name, False): if isinstance(f, FileField) and rel_new_data.get(f.name, False):
f.save_file(rel_new_data, new_rel_obj, change and old_rel_obj or None, old_rel_obj is not None, rel=True) f.save_file(rel_new_data, new_rel_obj, change and old_rel_obj or None, old_rel_obj is not None, rel=True)
# Calculate whether any fields have changed. # Calculate whether any fields have changed.
if change: if change:
if not old_rel_obj: # This object didn't exist before. if not old_rel_obj: # This object didn't exist before.
@ -198,27 +199,27 @@ class AutomaticManipulator(Manipulator):
for f in related.opts.fields: for f in related.opts.fields:
if not f.primary_key and f != related.field and str(getattr(old_rel_obj, f.attname)) != str(getattr(new_rel_obj, f.attname)): if not f.primary_key and f != related.field and str(getattr(old_rel_obj, f.attname)) != str(getattr(new_rel_obj, f.attname)):
self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj)) self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
# Save many-to-many objects. # Save many-to-many objects.
for f in related.opts.many_to_many: for f in related.opts.many_to_many:
if child_follow.get(f.name, None) and not f.rel.edit_inline: if child_follow.get(f.name, None) and not f.rel.edit_inline:
was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.attname]) was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.attname])
if change and was_changed: if change and was_changed:
self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj)) self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
# If, in the change stage, all of the core fields were blank and # If, in the change stage, all of the core fields were blank and
# the primary key (ID) was provided, delete the item. # the primary key (ID) was provided, delete the item.
if change and all_cores_blank and old_rel_obj: if change and all_cores_blank and old_rel_obj:
new_rel_obj.delete(ignore_objects=[new_object]) new_rel_obj.delete(ignore_objects=[new_object])
self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj)) self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj))
# Save the order, if applicable. # Save the order, if applicable.
if change and opts.get_ordered_objects(): if change and opts.get_ordered_objects():
order = new_data['order_'] and map(int, new_data['order_'].split(',')) or [] order = new_data['order_'] and map(int, new_data['order_'].split(',')) or []
for rel_opts in opts.get_ordered_objects(): for rel_opts in opts.get_ordered_objects():
getattr(new_object, 'set_%s_order' % rel_opts.object_name.lower())(order) getattr(new_object, 'set_%s_order' % rel_opts.object_name.lower())(order)
return new_object return new_object
def get_related_objects(self): def get_related_objects(self):
return self.opts.get_followed_related_objects(self.follow) return self.opts.get_followed_related_objects(self.follow)
@ -234,11 +235,11 @@ class ModelAddManipulator(AutomaticManipulator):
add = True add = True
def __init__(self, follow=None): def __init__(self, follow=None):
super(ModelAddManipulator, self).__init__(follow=follow) super(ModelAddManipulator, self).__init__(follow=follow)
class ModelChangeManipulator(AutomaticManipulator): class ModelChangeManipulator(AutomaticManipulator):
change = True change = True
add = False add = False
def __init__(self, obj_key=None, follow=None): def __init__(self, obj_key=None, follow=None):
assert obj_key is not None, "ChangeManipulator.__init__() must be passed obj_key parameter." assert obj_key is not None, "ChangeManipulator.__init__() must be passed obj_key parameter."
self.obj_key = obj_key self.obj_key = obj_key
@ -265,11 +266,11 @@ class ModelChangeManipulator(AutomaticManipulator):
super(ModelChangeManipulator, self).__init__(original_object=original_object, follow=follow) super(ModelChangeManipulator, self).__init__(original_object=original_object, follow=follow)
print "Back" print "Back"
self.original_object = original_object self.original_object = original_object
if self.opts.get_ordered_objects(): if self.opts.get_ordered_objects():
self.fields.append(formfields.CommaSeparatedIntegerField(field_name="order_")) self.fields.append(formfields.CommaSeparatedIntegerField(field_name="order_"))
def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data): def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data):
@ -329,4 +330,3 @@ def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_t
format_string = (lookup_type == 'date') and '%B %d, %Y' or '%B %Y' format_string = (lookup_type == 'date') and '%B %d, %Y' or '%B %Y'
raise validators.ValidationError, "Please enter a different %s. The one you entered is already being used for %s." % \ raise validators.ValidationError, "Please enter a different %s. The one you entered is already being used for %s." % \
(from_field.verbose_name, date_val.strftime(format_string)) (from_field.verbose_name, date_val.strftime(format_string))

View File

@ -1,11 +1,11 @@
class Signals(object): class Signals(object):
class_prepared = object() class_prepared = object()
pre_init= object() pre_init= object()
post_init = object() post_init = object()
pre_save = object() pre_save = object()
post_save = object() post_save = object()
pre_delete = object() pre_delete = object()
post_delete = object() post_delete = object()