diff options
| author | Gary Wilson Jr <gary.wilson@gmail.com> | 2008-08-27 07:19:44 +0000 |
|---|---|---|
| committer | Gary Wilson Jr <gary.wilson@gmail.com> | 2008-08-27 07:19:44 +0000 |
| commit | c2ba59fc1da5287d6286e2c2aca4083d5bafe056 (patch) | |
| tree | 26c05bc1b845efadd28126adee8f2a3726f09424 /django/db/models/fields | |
| parent | a1575766604205b3bddf0f05d13ad698c78a7582 (diff) | |
Removed oldforms, validators, and related code:
* Removed `Manipulator`, `AutomaticManipulator`, and related classes.
* Removed oldforms specific bits from model fields:
* Removed `validator_list` and `core` arguments from constructors.
* Removed the methods:
* `get_manipulator_field_names`
* `get_manipulator_field_objs`
* `get_manipulator_fields`
* `get_manipulator_new_data`
* `prepare_field_objs_and_params`
* `get_follow`
* Renamed `flatten_data` method to `value_to_string` for better alignment with its use by the serialization framework, which was the only remaining code using `flatten_data`.
* Removed oldforms methods from `django.db.models.Options` class: `get_followed_related_objects`, `get_data_holders`, `get_follow`, and `has_field_type`.
* Removed oldforms-admin specific options from `django.db.models.fields.related` classes: `num_in_admin`, `min_num_in_admin`, `max_num_in_admin`, `num_extra_on_change`, and `edit_inline`.
* Serialization framework
* `Serializer.get_string_value` now calls the model fields' renamed `value_to_string` methods.
* Removed a special-casing of `models.DateTimeField` in `core.serializers.base.Serializer.get_string_value` that's handled by `django.db.models.fields.DateTimeField.value_to_string`.
* Removed `django.core.validators`:
* Moved `ValidationError` exception to `django.core.exceptions`.
* For the couple places that were using validators, brought over the necessary code to maintain the same functionality.
* Introduced a SlugField form field for validation and to compliment the SlugField model field (refs #8040).
* Removed an oldforms-style model creation hack (refs #2160).
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8616 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/models/fields')
| -rw-r--r-- | django/db/models/fields/__init__.py | 313 | ||||
| -rw-r--r-- | django/db/models/fields/files.py | 54 | ||||
| -rw-r--r-- | django/db/models/fields/related.py | 98 |
3 files changed, 93 insertions, 372 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index b8d05671b1..5c21e7db73 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -1,6 +1,7 @@ import copy import datetime import os +import re import time try: import decimal @@ -12,10 +13,8 @@ from django.db.models import signals from django.db.models.query_utils import QueryWrapper from django.dispatch import dispatcher from django.conf import settings -from django.core import validators -from django import oldforms from django import forms -from django.core.exceptions import ObjectDoesNotExist +from django.core import exceptions from django.utils.datastructures import DictWrapper from django.utils.functional import curry from django.utils.itercompat import tee @@ -34,17 +33,6 @@ BLANK_CHOICE_NONE = [("", "None")] class FieldDoesNotExist(Exception): pass -def manipulator_validator_unique(f, opts, self, field_data, all_data): - "Validates that the value is unique for this field." - lookup_type = f.get_validator_unique_lookup_type() - try: - old_obj = self.manager.get(**{lookup_type: field_data}) - except ObjectDoesNotExist: - return - if getattr(self, 'original_object', None) and self.original_object._get_pk_val() == old_obj._get_pk_val(): - return - raise validators.ValidationError, _("%(optname)s with this %(fieldname)s already exists.") % {'optname': capfirst(opts.verbose_name), 'fieldname': f.verbose_name} - # A guide to Field parameters: # # * name: The name of the field specifed in the model. @@ -73,11 +61,10 @@ class Field(object): def __init__(self, verbose_name=None, name=None, primary_key=False, max_length=None, unique=False, blank=False, null=False, - db_index=False, core=False, rel=None, default=NOT_PROVIDED, - editable=True, serialize=True, unique_for_date=None, - unique_for_month=None, unique_for_year=None, validator_list=None, - choices=None, help_text='', db_column=None, db_tablespace=None, - auto_created=False): + db_index=False, rel=None, default=NOT_PROVIDED, editable=True, + serialize=True, unique_for_date=None, unique_for_month=None, + unique_for_year=None, choices=None, help_text='', db_column=None, + db_tablespace=None, auto_created=False): self.name = name self.verbose_name = verbose_name self.primary_key = primary_key @@ -87,10 +74,10 @@ class Field(object): # option whenever '' is a possible value. if self.empty_strings_allowed and connection.features.interprets_empty_strings_as_nulls: self.null = True - self.core, self.rel, self.default = core, rel, default + self.rel = rel + self.default = default self.editable = editable self.serialize = serialize - self.validator_list = validator_list or [] self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month self.unique_for_year = unique_for_year self._choices = choices or [] @@ -126,8 +113,8 @@ class Field(object): def to_python(self, value): """ Converts the input value into the expected Python data type, raising - validators.ValidationError if the data can't be converted. Returns the - converted value. Subclasses should override this. + django.core.exceptions.ValidationError if the data can't be converted. + Returns the converted value. Subclasses should override this. """ return value @@ -252,93 +239,9 @@ class Field(object): return None return "" - def get_manipulator_field_names(self, name_prefix): - """ - Returns a list of field names that this object adds to the manipulator. - """ - return [name_prefix + self.name] - - def prepare_field_objs_and_params(self, manipulator, name_prefix): - params = {'validator_list': self.validator_list[:]} - if self.max_length and not self.choices: # Don't give SelectFields a max_length parameter. - params['max_length'] = self.max_length - - if self.choices: - field_objs = [oldforms.SelectField] - - params['choices'] = self.get_flatchoices() - else: - field_objs = self.get_manipulator_field_objs() - return (field_objs, params) - - def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): - """ - Returns a list of oldforms.FormField instances for this field. It - calculates the choices at runtime, not at compile time. - - name_prefix is a prefix to prepend to the "field_name" argument. - rel is a boolean specifying whether this field is in a related context. - """ - field_objs, params = self.prepare_field_objs_and_params(manipulator, name_prefix) - - # Add the "unique" validator(s). - for field_name_list in opts.unique_together: - if field_name_list[0] == self.name: - params['validator_list'].append(getattr(manipulator, 'isUnique%s' % '_'.join(field_name_list))) - - # Add the "unique for..." validator(s). - if self.unique_for_date: - params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_date))) - if self.unique_for_month: - params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_month))) - if self.unique_for_year: - params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_year))) - if self.unique and not rel: - params['validator_list'].append(curry(manipulator_validator_unique, self, opts, manipulator)) - - # Only add is_required=True if the field cannot be blank. Primary keys - # are a special case, and fields in a related context should set this - # as False, because they'll be caught by a separate validator -- - # RequiredIfOtherFieldGiven. - params['is_required'] = not self.blank and not self.primary_key and not rel - - # BooleanFields (CheckboxFields) are a special case. They don't take - # is_required. - if isinstance(self, BooleanField): - del params['is_required'] - - # If this field is in a related context, check whether any other fields - # in the related object have core=True. If so, add a validator -- - # RequiredIfOtherFieldsGiven -- to this FormField. - if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, FileField): - # First, get the core fields, if any. - core_field_names = [] - for f in opts.fields: - if f.core and f != self: - core_field_names.extend(f.get_manipulator_field_names(name_prefix)) - # Now, if there are any, add the validator to this FormField. - if core_field_names: - params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, ugettext_lazy("This field is required."))) - - # Finally, add the field_names. - field_names = self.get_manipulator_field_names(name_prefix) - return [man(field_name=field_names[i], **params) for i, man in enumerate(field_objs)] - def get_validator_unique_lookup_type(self): return '%s__exact' % self.name - def get_manipulator_new_data(self, new_data, rel=False): - """ - Given the full new_data dictionary (from the manipulator), returns this - field's data. - """ - if rel: - return new_data.get(self.name, [self.get_default()])[0] - val = new_data.get(self.name, self.get_default()) - if not self.empty_strings_allowed and val == '' and self.null: - val = None - return val - def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): """Returns choices with a default blank choices included, for use as SelectField choices for this field.""" @@ -366,19 +269,12 @@ class Field(object): else: return self.get_default() - def flatten_data(self, follow, obj=None): + def value_to_string(self, obj): """ - Returns a dictionary mapping the field's manipulator field names to its - "flattened" string values for the admin view. obj is the instance to - extract the values from. + Returns a string value of this field from the passed obj. + This is used by the serialization framework. """ - return {self.attname: self._get_val_from_obj(obj)} - - def get_follow(self, override=None): - if override != None: - return override - else: - return self.editable + return smart_unicode(self._get_val_from_obj(obj)) def bind(self, fieldmapping, original, bound_field_class): return bound_field_class(self, fieldmapping, original) @@ -432,29 +328,14 @@ class AutoField(Field): try: return int(value) except (TypeError, ValueError): - raise validators.ValidationError, _("This value must be an integer.") + raise exceptions.ValidationError( + _("This value must be an integer.")) def get_db_prep_value(self, value): if value is None: return None return int(value) - def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): - if not rel: - return [] # Don't add a FormField unless it's in a related context. - return Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow) - - def get_manipulator_field_objs(self): - return [oldforms.HiddenField] - - def get_manipulator_new_data(self, new_data, rel=False): - # Never going to be called - # Not in main change pages - # ignored in related context - if not rel: - return None - return Field.get_manipulator_new_data(self, new_data, rel) - def contribute_to_class(self, cls, name): assert not cls._meta.has_auto_field, "A model can't have more than one AutoField." super(AutoField, self).contribute_to_class(cls, name) @@ -478,25 +359,20 @@ class BooleanField(Field): if value in (True, False): return value if value in ('t', 'True', '1'): return True if value in ('f', 'False', '0'): return False - raise validators.ValidationError, _("This value must be either True or False.") + raise exceptions.ValidationError( + _("This value must be either True or False.")) def get_db_prep_value(self, value): if value is None: return None return bool(value) - def get_manipulator_field_objs(self): - return [oldforms.CheckboxField] - def formfield(self, **kwargs): defaults = {'form_class': forms.BooleanField} defaults.update(kwargs) return super(BooleanField, self).formfield(**defaults) class CharField(Field): - def get_manipulator_field_objs(self): - return [oldforms.TextField] - def get_internal_type(self): return "CharField" @@ -507,7 +383,8 @@ class CharField(Field): if self.null: return value else: - raise validators.ValidationError, ugettext_lazy("This field cannot be null.") + raise exceptions.ValidationError( + ugettext_lazy("This field cannot be null.")) return smart_unicode(value) def formfield(self, **kwargs): @@ -517,8 +394,9 @@ class CharField(Field): # TODO: Maybe move this into contrib, because it's specialized. class CommaSeparatedIntegerField(CharField): - def get_manipulator_field_objs(self): - return [oldforms.CommaSeparatedIntegerField] + pass + +ansi_date_re = re.compile(r'^\d{4}-\d{1,2}-\d{1,2}$') class DateField(Field): empty_strings_allowed = False @@ -540,11 +418,20 @@ class DateField(Field): return value.date() if isinstance(value, datetime.date): return value - validators.isValidANSIDate(value, None) + + if not ansi_date_re.search(value): + raise exceptions.ValidationError( + _('Enter a valid date in YYYY-MM-DD format.')) + # Now that we have the date string in YYYY-MM-DD format, check to make + # sure it's a valid date. + # We could use time.strptime here and catch errors, but datetime.date + # produces much friendlier error messages. + year, month, day = map(int, value.split('-')) try: - return datetime.date(*time.strptime(value, '%Y-%m-%d')[:3]) - except ValueError: - raise validators.ValidationError, _('Enter a valid date in YYYY-MM-DD format.') + return datetime.date(year, month, day) + except ValueError, e: + msg = _('Invalid date: %s') % _(str(e)) + raise exceptions.ValidationError(msg) def pre_save(self, model_instance, add): if self.auto_now or (self.auto_now_add and add): @@ -562,13 +449,6 @@ class DateField(Field): setattr(cls, 'get_previous_by_%s' % self.name, curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False)) - # Needed because of horrible auto_now[_add] behaviour wrt. editable - def get_follow(self, override=None): - if override != None: - return override - else: - return self.editable or self.auto_now or self.auto_now_add - def get_db_prep_lookup(self, lookup_type, value): # For "__month" and "__day" lookups, convert the value to a string so # the database backend always sees a consistent type. @@ -580,16 +460,13 @@ class DateField(Field): # Casts dates into the format expected by the backend return connection.ops.value_to_db_date(self.to_python(value)) - def get_manipulator_field_objs(self): - return [oldforms.DateField] - - def flatten_data(self, follow, obj=None): + def value_to_string(self, obj): val = self._get_val_from_obj(obj) if val is None: data = '' else: data = datetime_safe.new_date(val).strftime("%Y-%m-%d") - return {self.attname: data} + return data def formfield(self, **kwargs): defaults = {'form_class': forms.DateField} @@ -616,7 +493,8 @@ class DateTimeField(DateField): value, usecs = value.split('.') usecs = int(usecs) except ValueError: - raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.') + raise exceptions.ValidationError( + _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')) else: usecs = 0 kwargs = {'microsecond': usecs} @@ -633,40 +511,21 @@ class DateTimeField(DateField): return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3], **kwargs) except ValueError: - raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.') + raise exceptions.ValidationError( + _('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.')) def get_db_prep_value(self, value): # Casts dates into the format expected by the backend return connection.ops.value_to_db_datetime(self.to_python(value)) - def get_manipulator_field_objs(self): - return [oldforms.DateField, oldforms.TimeField] - - def get_manipulator_field_names(self, name_prefix): - return [name_prefix + self.name + '_date', name_prefix + self.name + '_time'] - - def get_manipulator_new_data(self, new_data, rel=False): - date_field, time_field = self.get_manipulator_field_names('') - if rel: - d = new_data.get(date_field, [None])[0] - t = new_data.get(time_field, [None])[0] - else: - d = new_data.get(date_field, None) - t = new_data.get(time_field, None) - if d is not None and t is not None: - return datetime.datetime.combine(d, t) - return self.get_default() - - def flatten_data(self,follow, obj = None): + def value_to_string(self, obj): val = self._get_val_from_obj(obj) - date_field, time_field = self.get_manipulator_field_names('') if val is None: - date_data = time_data = '' + data = '' else: d = datetime_safe.new_datetime(val) - date_data = d.strftime('%Y-%m-%d') - time_data = d.strftime('%H:%M:%S') - return {date_field: date_data, time_field: time_data} + data = d.strftime('%Y-%m-%d %H:%M:%S') + return data def formfield(self, **kwargs): defaults = {'form_class': forms.DateTimeField} @@ -688,7 +547,7 @@ class DecimalField(Field): try: return decimal.Decimal(value) except decimal.InvalidOperation: - raise validators.ValidationError( + raise exceptions.ValidationError( _("This value must be a decimal number.")) def _format(self, value): @@ -715,9 +574,6 @@ class DecimalField(Field): return connection.ops.value_to_db_decimal(self.to_python(value), self.max_digits, self.decimal_places) - def get_manipulator_field_objs(self): - return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)] - def formfield(self, **kwargs): defaults = { 'max_digits': self.max_digits, @@ -732,9 +588,6 @@ class EmailField(CharField): kwargs['max_length'] = kwargs.get('max_length', 75) CharField.__init__(self, *args, **kwargs) - def get_manipulator_field_objs(self): - return [oldforms.EmailField] - def formfield(self, **kwargs): defaults = {'form_class': forms.EmailField} defaults.update(kwargs) @@ -756,9 +609,6 @@ class FilePathField(Field): defaults.update(kwargs) return super(FilePathField, self).formfield(**defaults) - def get_manipulator_field_objs(self): - return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)] - def get_internal_type(self): return "FilePathField" @@ -770,9 +620,6 @@ class FloatField(Field): return None return float(value) - def get_manipulator_field_objs(self): - return [oldforms.FloatField] - def get_internal_type(self): return "FloatField" @@ -788,9 +635,6 @@ class IntegerField(Field): return None return int(value) - def get_manipulator_field_objs(self): - return [oldforms.IntegerField] - def get_internal_type(self): return "IntegerField" @@ -800,8 +644,9 @@ class IntegerField(Field): try: return int(value) except (TypeError, ValueError): - raise validators.ValidationError, _("This value must be an integer.") - + raise exceptions.ValidationError( + _("This value must be an integer.")) + def formfield(self, **kwargs): defaults = {'form_class': forms.IntegerField} defaults.update(kwargs) @@ -813,9 +658,6 @@ class IPAddressField(Field): kwargs['max_length'] = 15 Field.__init__(self, *args, **kwargs) - def get_manipulator_field_objs(self): - return [oldforms.IPAddressField] - def get_internal_type(self): return "IPAddressField" @@ -838,16 +680,14 @@ class NullBooleanField(Field): if value in ('None'): return None if value in ('t', 'True', '1'): return True if value in ('f', 'False', '0'): return False - raise validators.ValidationError, _("This value must be either None, True or False.") + raise exceptions.ValidationError( + _("This value must be either None, True or False.")) def get_db_prep_value(self, value): if value is None: return None return bool(value) - def get_manipulator_field_objs(self): - return [oldforms.NullBooleanField] - def formfield(self, **kwargs): defaults = { 'form_class': forms.NullBooleanField, @@ -858,9 +698,6 @@ class NullBooleanField(Field): return super(NullBooleanField, self).formfield(**defaults) class PhoneNumberField(Field): - def get_manipulator_field_objs(self): - return [oldforms.PhoneNumberField] - def get_internal_type(self): return "PhoneNumberField" @@ -871,9 +708,6 @@ class PhoneNumberField(Field): return super(PhoneNumberField, self).formfield(**defaults) class PositiveIntegerField(IntegerField): - def get_manipulator_field_objs(self): - return [oldforms.PositiveIntegerField] - def get_internal_type(self): return "PositiveIntegerField" @@ -883,9 +717,6 @@ class PositiveIntegerField(IntegerField): return super(PositiveIntegerField, self).formfield(**defaults) class PositiveSmallIntegerField(IntegerField): - def get_manipulator_field_objs(self): - return [oldforms.PositiveSmallIntegerField] - def get_internal_type(self): return "PositiveSmallIntegerField" @@ -897,7 +728,6 @@ class PositiveSmallIntegerField(IntegerField): class SlugField(CharField): def __init__(self, *args, **kwargs): kwargs['max_length'] = kwargs.get('max_length', 50) - kwargs.setdefault('validator_list', []).append(validators.isSlug) # Set db_index=True unless it's been set manually. if 'db_index' not in kwargs: kwargs['db_index'] = True @@ -907,23 +737,15 @@ class SlugField(CharField): return "SlugField" def formfield(self, **kwargs): - defaults = {'form_class': forms.RegexField, 'regex': r'^[a-zA-Z0-9_-]+$', - 'error_messages': {'invalid': _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.")}, - } + defaults = {'form_class': forms.SlugField} defaults.update(kwargs) return super(SlugField, self).formfield(**defaults) class SmallIntegerField(IntegerField): - def get_manipulator_field_objs(self): - return [oldforms.SmallIntegerField] - def get_internal_type(self): return "SmallIntegerField" class TextField(Field): - def get_manipulator_field_objs(self): - return [oldforms.LargeTextField] - def get_internal_type(self): return "TextField" @@ -957,7 +779,8 @@ class TimeField(Field): value, usecs = value.split('.') usecs = int(usecs) except ValueError: - raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') + raise exceptions.ValidationError( + _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')) else: usecs = 0 kwargs = {'microsecond': usecs} @@ -970,7 +793,8 @@ class TimeField(Field): return datetime.time(*time.strptime(value, '%H:%M')[3:5], **kwargs) except ValueError: - raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') + raise exceptions.ValidationError( + _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.')) def pre_save(self, model_instance, add): if self.auto_now or (self.auto_now_add and add): @@ -984,12 +808,13 @@ class TimeField(Field): # Casts times into the format expected by the backend return connection.ops.value_to_db_time(self.to_python(value)) - def get_manipulator_field_objs(self): - return [oldforms.TimeField] - - def flatten_data(self,follow, obj = None): + def value_to_string(self, obj): val = self._get_val_from_obj(obj) - return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')} + if val is None: + data = '' + else: + data = val.strftime("%H:%M:%S") + return data def formfield(self, **kwargs): defaults = {'form_class': forms.TimeField} @@ -999,23 +824,15 @@ class TimeField(Field): class URLField(CharField): def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs): kwargs['max_length'] = kwargs.get('max_length', 200) - if verify_exists: - kwargs.setdefault('validator_list', []).append(validators.isExistingURL) self.verify_exists = verify_exists CharField.__init__(self, verbose_name, name, **kwargs) - def get_manipulator_field_objs(self): - return [oldforms.URLField] - def formfield(self, **kwargs): defaults = {'form_class': forms.URLField, 'verify_exists': self.verify_exists} defaults.update(kwargs) return super(URLField, self).formfield(**defaults) class USStateField(Field): - def get_manipulator_field_objs(self): - return [oldforms.USStateField] - def get_internal_type(self): return "USStateField" @@ -1029,7 +846,3 @@ class XMLField(TextField): def __init__(self, verbose_name=None, name=None, schema_path=None, **kwargs): self.schema_path = schema_path Field.__init__(self, verbose_name, name, **kwargs) - - def get_manipulator_field_objs(self): - return [curry(oldforms.XMLLargeTextField, schema_path=self.schema_path)] - diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index 935dee6162..f83f0cf575 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -11,9 +11,7 @@ from django.utils.functional import curry from django.db.models import signals from django.utils.encoding import force_unicode, smart_str from django.utils.translation import ugettext_lazy, ugettext as _ -from django import oldforms from django import forms -from django.core import validators from django.db.models.loading import cache class FieldFile(File): @@ -126,7 +124,7 @@ class FileField(Field): attr_class = FieldFile def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): - for arg in ('core', 'primary_key', 'unique'): + for arg in ('primary_key', 'unique'): if arg in kwargs: raise TypeError("'%s' is not a valid argument for %s." % (arg, self.__class__)) @@ -153,42 +151,6 @@ class FileField(Field): return None return unicode(value) - def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): - field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow) - if not self.blank: - if rel: - # This validator makes sure FileFields work in a related context. - class RequiredFileField(object): - def __init__(self, other_field_names, other_file_field_name): - self.other_field_names = other_field_names - self.other_file_field_name = other_file_field_name - self.always_test = True - def __call__(self, field_data, all_data): - if not all_data.get(self.other_file_field_name, False): - c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required.")) - c(field_data, all_data) - # First, get the core fields, if any. - core_field_names = [] - for f in opts.fields: - if f.core and f != self: - core_field_names.extend(f.get_manipulator_field_names(name_prefix)) - # Now, if there are any, add the validator to this FormField. - if core_field_names: - field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) - else: - v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required.")) - v.always_test = True - field_list[0].validator_list.append(v) - field_list[0].is_required = field_list[1].is_required = False - - # If the raw path is passed in, validate it's under the MEDIA_ROOT. - def isWithinMediaRoot(field_data, all_data): - f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) - if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))): - raise validators.ValidationError(_("Enter a valid filename.")) - field_list[1].validator_list.append(isWithinMediaRoot) - return field_list - def contribute_to_class(self, cls, name): super(FileField, self).contribute_to_class(cls, name) setattr(cls, self.name, FileDescriptor(self)) @@ -206,14 +168,9 @@ class FileField(Field): # Otherwise, just close the file, so it doesn't tie up resources. file.close() - def get_manipulator_field_objs(self): - return [oldforms.FileUploadField, oldforms.HiddenField] - - def get_manipulator_field_names(self, name_prefix): - return [name_prefix + self.name + '_file', name_prefix + self.name] - - def save_file(self, new_data, new_object, original_object, change, rel, save=True): - upload_field_name = self.get_manipulator_field_names('')[0] + def save_file(self, new_data, new_object, original_object, change, rel, + save=True): + upload_field_name = self.name + '_file' if new_data.get(upload_field_name, False): if rel: file = new_data[upload_field_name][0] @@ -282,9 +239,6 @@ class ImageField(FileField): self.width_field, self.height_field = width_field, height_field FileField.__init__(self, verbose_name, name, **kwargs) - def get_manipulator_field_objs(self): - return [oldforms.ImageUploadField, oldforms.HiddenField] - def formfield(self, **kwargs): defaults = {'form_class': forms.ImageField} defaults.update(kwargs) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 7601911f0c..db606e5042 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -4,10 +4,10 @@ from django.db.models.fields import AutoField, Field, IntegerField, PositiveInte from django.db.models.related import RelatedObject from django.db.models.query import QuerySet from django.db.models.query_utils import QueryWrapper +from django.utils.encoding import smart_unicode from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _ from django.utils.functional import curry -from django.core import validators -from django import oldforms +from django.core import exceptions from django import forms try: @@ -15,9 +15,6 @@ try: except NameError: from sets import Set as set # Python 2.3 fallback -# Values for Relation.edit_inline. -TABULAR, STACKED = 1, 2 - RECURSIVE_RELATIONSHIP_CONSTANT = 'self' pending_lookups = {} @@ -83,14 +80,6 @@ def do_pending_lookups(sender, **kwargs): signals.class_prepared.connect(do_pending_lookups) -def manipulator_valid_rel_key(f, self, field_data, all_data): - "Validates that the value is a valid foreign key" - klass = f.rel.to - try: - klass._default_manager.get(**{f.rel.field_name: field_data}) - except klass.DoesNotExist: - raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name - #HACK class RelatedField(object): def contribute_to_class(self, cls, name): @@ -580,18 +569,14 @@ class ReverseManyRelatedObjectsDescriptor(object): manager.add(*value) class ManyToOneRel(object): - def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, - max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, - related_name=None, limit_choices_to=None, lookup_overrides=None, - parent_link=False): + def __init__(self, to, field_name, related_name=None, + limit_choices_to=None, lookup_overrides=None, parent_link=False): try: to._meta except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT self.to, self.field_name = to, field_name - self.num_in_admin, self.edit_inline = num_in_admin, edit_inline - self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin - self.num_extra_on_change, self.related_name = num_extra_on_change, related_name + self.related_name = related_name if limit_choices_to is None: limit_choices_to = {} self.limit_choices_to = limit_choices_to @@ -611,29 +596,21 @@ class ManyToOneRel(object): return data[0] class OneToOneRel(ManyToOneRel): - def __init__(self, to, field_name, num_in_admin=0, min_num_in_admin=None, - max_num_in_admin=None, num_extra_on_change=None, edit_inline=False, - related_name=None, limit_choices_to=None, lookup_overrides=None, - parent_link=False): - # NOTE: *_num_in_admin and num_extra_on_change are intentionally - # ignored here. We accept them as parameters only to match the calling - # signature of ManyToOneRel.__init__(). - super(OneToOneRel, self).__init__(to, field_name, num_in_admin, - edit_inline=edit_inline, related_name=related_name, - limit_choices_to=limit_choices_to, + def __init__(self, to, field_name, related_name=None, + limit_choices_to=None, lookup_overrides=None, parent_link=False): + super(OneToOneRel, self).__init__(to, field_name, + related_name=related_name, limit_choices_to=limit_choices_to, lookup_overrides=lookup_overrides, parent_link=parent_link) self.multiple = False class ManyToManyRel(object): - def __init__(self, to, num_in_admin=0, related_name=None, - limit_choices_to=None, symmetrical=True, through=None): + def __init__(self, to, related_name=None, limit_choices_to=None, + symmetrical=True, through=None): self.to = to - self.num_in_admin = num_in_admin self.related_name = related_name if limit_choices_to is None: limit_choices_to = {} self.limit_choices_to = limit_choices_to - self.edit_inline = False self.symmetrical = symmetrical self.multiple = True self.through = through @@ -651,11 +628,6 @@ class ForeignKey(RelatedField, Field): kwargs['verbose_name'] = kwargs.get('verbose_name', None) kwargs['rel'] = rel_class(to, to_field, - num_in_admin=kwargs.pop('num_in_admin', 3), - min_num_in_admin=kwargs.pop('min_num_in_admin', None), - max_num_in_admin=kwargs.pop('max_num_in_admin', None), - num_extra_on_change=kwargs.pop('num_extra_on_change', 1), - edit_inline=kwargs.pop('edit_inline', False), related_name=kwargs.pop('related_name', None), limit_choices_to=kwargs.pop('limit_choices_to', None), lookup_overrides=kwargs.pop('lookup_overrides', None), @@ -670,15 +642,6 @@ class ForeignKey(RelatedField, Field): def get_validator_unique_lookup_type(self): return '%s__%s__exact' % (self.name, self.rel.get_related_field().name) - def prepare_field_objs_and_params(self, manipulator, name_prefix): - params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname} - if self.null: - field_objs = [oldforms.NullSelectField] - else: - field_objs = [oldforms.SelectField] - params['choices'] = self.get_choices_default() - return field_objs, params - def get_default(self): "Here we check if the default value is an object and return the to_field if so." field_default = super(ForeignKey, self).get_default() @@ -686,17 +649,13 @@ class ForeignKey(RelatedField, Field): return getattr(field_default, self.rel.get_related_field().attname) return field_default - def get_manipulator_field_objs(self): - rel_field = self.rel.get_related_field() - return [oldforms.IntegerField] - def get_db_prep_save(self, value): if value == '' or value == None: return None else: return self.rel.get_related_field().get_db_prep_save(value) - def flatten_data(self, follow, obj=None): + def value_to_string(self, obj): if not obj: # In required many-to-one fields with only one available choice, # select that one available choice. Note: For SelectFields @@ -705,8 +664,8 @@ class ForeignKey(RelatedField, Field): if not self.blank and self.choices: choice_list = self.get_choices_default() if len(choice_list) == 2: - return {self.attname: choice_list[1][0]} - return Field.flatten_data(self, follow, obj) + return smart_unicode(choice_list[1][0]) + return Field.value_to_string(self, obj) def contribute_to_class(self, cls, name): super(ForeignKey, self).contribute_to_class(cls, name) @@ -744,8 +703,6 @@ class OneToOneField(ForeignKey): """ def __init__(self, to, to_field=None, **kwargs): kwargs['unique'] = True - if 'num_in_admin' not in kwargs: - kwargs['num_in_admin'] = 0 super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs) def contribute_to_related_class(self, cls, related): @@ -768,7 +725,6 @@ class ManyToManyField(RelatedField, Field): kwargs['verbose_name'] = kwargs.get('verbose_name', None) kwargs['rel'] = ManyToManyRel(to, - num_in_admin=kwargs.pop('num_in_admin', 0), related_name=kwargs.pop('related_name', None), limit_choices_to=kwargs.pop('limit_choices_to', None), symmetrical=kwargs.pop('symmetrical', True), @@ -786,10 +742,6 @@ class ManyToManyField(RelatedField, Field): msg = ugettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.') self.help_text = string_concat(self.help_text, ' ', msg) - def get_manipulator_field_objs(self): - choices = self.get_choices_default() - return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)] - def get_choices_default(self): return Field.get_choices(self, include_blank=False) @@ -863,25 +815,27 @@ class ManyToManyField(RelatedField, Field): objects = mod._default_manager.in_bulk(pks) if len(objects) != len(pks): badkeys = [k for k in pks if k not in objects] - raise validators.ValidationError, ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.", - "Please enter valid %(self)s IDs. The values %(value)r are invalid.", len(badkeys)) % { + raise exceptions.ValidationError( + ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.", + "Please enter valid %(self)s IDs. The values %(value)r are invalid.", + len(badkeys)) % { 'self': self.verbose_name, 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys), - } + }) - def flatten_data(self, follow, obj = None): - new_data = {} + def value_to_string(self, obj): + data = '' if obj: - instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()] - new_data[self.name] = instance_ids + qs = getattr(obj, self.name).all() + data = [instance._get_pk_val() for instance in qs] else: # In required many-to-many fields with only one available choice, # select that one available choice. - if not self.blank and not self.rel.edit_inline: + if not self.blank: choices_list = self.get_choices_default() if len(choices_list) == 1: - new_data[self.name] = [choices_list[0][0]] - return new_data + data = [choices_list[0][0]] + return smart_unicode(data) def contribute_to_class(self, cls, name): super(ManyToManyField, self).contribute_to_class(cls, name) |
