| 1 |
from django.conf import settings |
|---|
| 2 |
from django.core import formfields, validators |
|---|
| 3 |
from django.core import db |
|---|
| 4 |
from django.core.exceptions import ObjectDoesNotExist |
|---|
| 5 |
from django.utils.functional import curry |
|---|
| 6 |
from django.utils.text import capfirst |
|---|
| 7 |
import datetime, os |
|---|
| 8 |
|
|---|
| 9 |
# Random entropy string used by "default" param. |
|---|
| 10 |
NOT_PROVIDED = 'oijpwojefiojpanv' |
|---|
| 11 |
|
|---|
| 12 |
# Values for filter_interface. |
|---|
| 13 |
HORIZONTAL, VERTICAL = 1, 2 |
|---|
| 14 |
|
|---|
| 15 |
# The values to use for "blank" in SelectFields. Will be appended to the start of most "choices" lists. |
|---|
| 16 |
BLANK_CHOICE_DASH = [("", "---------")] |
|---|
| 17 |
BLANK_CHOICE_NONE = [("", "None")] |
|---|
| 18 |
|
|---|
| 19 |
# Values for Relation.edit_inline. |
|---|
| 20 |
TABULAR, STACKED = 1, 2 |
|---|
| 21 |
|
|---|
| 22 |
RECURSIVE_RELATIONSHIP_CONSTANT = 'self' |
|---|
| 23 |
|
|---|
| 24 |
# prepares a value for use in a LIKE query |
|---|
| 25 |
prep_for_like_query = lambda x: str(x).replace("%", "\%").replace("_", "\_") |
|---|
| 26 |
|
|---|
| 27 |
# returns the <ul> class for a given radio_admin value |
|---|
| 28 |
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '') |
|---|
| 29 |
|
|---|
| 30 |
def manipulator_valid_rel_key(f, self, field_data, all_data): |
|---|
| 31 |
"Validates that the value is a valid foreign key" |
|---|
| 32 |
mod = f.rel.to.get_model_module() |
|---|
| 33 |
try: |
|---|
| 34 |
mod.get_object(**{'id__iexact': field_data}) |
|---|
| 35 |
except ObjectDoesNotExist: |
|---|
| 36 |
raise validators.ValidationError, "Please enter a valid %s." % f.verbose_name |
|---|
| 37 |
|
|---|
| 38 |
def manipulator_validator_unique(f, opts, self, field_data, all_data): |
|---|
| 39 |
"Validates that the value is unique for this field." |
|---|
| 40 |
try: |
|---|
| 41 |
old_obj = opts.get_model_module().get_object(**{'%s__exact' % f.name: field_data}) |
|---|
| 42 |
except ObjectDoesNotExist: |
|---|
| 43 |
return |
|---|
| 44 |
if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.name) == getattr(old_obj, opts.pk.name): |
|---|
| 45 |
return |
|---|
| 46 |
raise validators.ValidationError, "%s with this %s already exists." % (capfirst(opts.verbose_name), f.verbose_name) |
|---|
| 47 |
|
|---|
| 48 |
class Field(object): |
|---|
| 49 |
|
|---|
| 50 |
# Designates whether empty strings fundamentally are allowed at the |
|---|
| 51 |
# database level. |
|---|
| 52 |
empty_strings_allowed = True |
|---|
| 53 |
|
|---|
| 54 |
def __init__(self, name, verbose_name=None, primary_key=False, |
|---|
| 55 |
maxlength=None, unique=False, blank=False, null=False, db_index=None, |
|---|
| 56 |
core=False, rel=None, default=NOT_PROVIDED, editable=True, |
|---|
| 57 |
prepopulate_from=None, unique_for_date=None, unique_for_month=None, |
|---|
| 58 |
unique_for_year=None, validator_list=None, choices=None, radio_admin=None, |
|---|
| 59 |
help_text=''): |
|---|
| 60 |
self.name = name |
|---|
| 61 |
self.verbose_name = verbose_name or name.replace('_', ' ') |
|---|
| 62 |
self.primary_key = primary_key |
|---|
| 63 |
self.maxlength, self.unique = maxlength, unique |
|---|
| 64 |
self.blank, self.null = blank, null |
|---|
| 65 |
self.core, self.rel, self.default = core, rel, default |
|---|
| 66 |
self.editable = editable |
|---|
| 67 |
self.validator_list = validator_list or [] |
|---|
| 68 |
self.prepopulate_from = prepopulate_from |
|---|
| 69 |
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month |
|---|
| 70 |
self.unique_for_year = unique_for_year |
|---|
| 71 |
self.choices = choices or [] |
|---|
| 72 |
self.radio_admin = radio_admin |
|---|
| 73 |
self.help_text = help_text |
|---|
| 74 |
if rel and isinstance(rel, ManyToMany): |
|---|
| 75 |
self.help_text += ' Hold down "Control", or "Command" on a Mac, to select more than one.' |
|---|
| 76 |
|
|---|
| 77 |
# Set db_index to True if the field has a relationship and doesn't explicitly set db_index. |
|---|
| 78 |
if db_index is None: |
|---|
| 79 |
if isinstance(rel, OneToOne) or isinstance(rel, ManyToOne): |
|---|
| 80 |
self.db_index = True |
|---|
| 81 |
else: |
|---|
| 82 |
self.db_index = False |
|---|
| 83 |
else: |
|---|
| 84 |
self.db_index = db_index |
|---|
| 85 |
|
|---|
| 86 |
def pre_save(self, value, add): |
|---|
| 87 |
"Returns field's value just before saving." |
|---|
| 88 |
return value |
|---|
| 89 |
|
|---|
| 90 |
def get_db_prep_save(self, value): |
|---|
| 91 |
"Returns field's value prepared for saving into a database." |
|---|
| 92 |
|
|---|
| 93 |
# Oracle treats empty strings ('') the same as NULLs. |
|---|
| 94 |
# To get around this wart, we need to change it to something else... |
|---|
| 95 |
if value == '': |
|---|
| 96 |
string_replacement = getattr(db,'EMPTY_STR_EQUIV','') |
|---|
| 97 |
value = string_replacement |
|---|
| 98 |
return value |
|---|
| 99 |
|
|---|
| 100 |
def get_db_prep_lookup(self, lookup_type, value): |
|---|
| 101 |
"Returns field's value prepared for database lookup." |
|---|
| 102 |
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne', 'month', 'day'): |
|---|
| 103 |
return [value] |
|---|
| 104 |
elif lookup_type in ('range', 'in'): |
|---|
| 105 |
return value |
|---|
| 106 |
elif lookup_type == 'year': |
|---|
| 107 |
return ['%s-01-01' % value, '%s-12-31' % value] |
|---|
| 108 |
elif lookup_type in ('contains', 'icontains'): |
|---|
| 109 |
return ["%%%s%%" % prep_for_like_query(value)] |
|---|
| 110 |
elif lookup_type == 'iexact': |
|---|
| 111 |
return [prep_for_like_query(value)] |
|---|
| 112 |
elif lookup_type in ('startswith', 'istartswith'): |
|---|
| 113 |
return ["%s%%" % prep_for_like_query(value)] |
|---|
| 114 |
elif lookup_type in ('endswith', 'iendswith'): |
|---|
| 115 |
return ["%%%s" % prep_for_like_query(value)] |
|---|
| 116 |
elif lookup_type == 'isnull': |
|---|
| 117 |
return [] |
|---|
| 118 |
raise TypeError, "Field has invalid lookup: %s" % lookup_type |
|---|
| 119 |
|
|---|
| 120 |
def has_default(self): |
|---|
| 121 |
"Returns a boolean of whether this field has a default value." |
|---|
| 122 |
return self.default != NOT_PROVIDED |
|---|
| 123 |
|
|---|
| 124 |
def get_default(self): |
|---|
| 125 |
"Returns the default value for this field." |
|---|
| 126 |
if self.default != NOT_PROVIDED: |
|---|
| 127 |
if hasattr(self.default, '__get_value__'): |
|---|
| 128 |
return self.default.__get_value__() |
|---|
| 129 |
return self.default |
|---|
| 130 |
if self.null: |
|---|
| 131 |
return None |
|---|
| 132 |
return "" |
|---|
| 133 |
|
|---|
| 134 |
def get_manipulator_field_names(self, name_prefix): |
|---|
| 135 |
""" |
|---|
| 136 |
Returns a list of field names that this object adds to the manipulator. |
|---|
| 137 |
""" |
|---|
| 138 |
return [name_prefix + self.name] |
|---|
| 139 |
|
|---|
| 140 |
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False): |
|---|
| 141 |
""" |
|---|
| 142 |
Returns a list of formfields.FormField instances for this field. It |
|---|
| 143 |
calculates the choices at runtime, not at compile time. |
|---|
| 144 |
|
|---|
| 145 |
name_prefix is a prefix to prepend to the "field_name" argument. |
|---|
| 146 |
rel is a boolean specifying whether this field is in a related context. |
|---|
| 147 |
""" |
|---|
| 148 |
params = {'validator_list': self.validator_list[:]} |
|---|
| 149 |
if self.maxlength and not self.choices: # Don't give SelectFields a maxlength parameter. |
|---|
| 150 |
params['maxlength'] = self.maxlength |
|---|
| 151 |
if isinstance(self.rel, ManyToOne): |
|---|
| 152 |
if self.rel.raw_id_admin: |
|---|
| 153 |
field_objs = self.get_manipulator_field_objs() |
|---|
| 154 |
params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator)) |
|---|
| 155 |
else: |
|---|
| 156 |
if self.radio_admin: |
|---|
| 157 |
field_objs = [formfields.RadioSelectField] |
|---|
| 158 |
params['choices'] = self.get_choices(include_blank=self.blank, blank_choice=BLANK_CHOICE_NONE) |
|---|
| 159 |
params['ul_class'] = get_ul_class(self.radio_admin) |
|---|
| 160 |
else: |
|---|
| 161 |
if self.null: |
|---|
| 162 |
field_objs = [formfields.NullSelectField] |
|---|
| 163 |
else: |
|---|
| 164 |
field_objs = [formfields.SelectField] |
|---|
| 165 |
params['choices'] = self.get_choices() |
|---|
| 166 |
elif self.choices: |
|---|
| 167 |
if self.radio_admin: |
|---|
| 168 |
field_objs = [formfields.RadioSelectField] |
|---|
| 169 |
params['choices'] = self.get_choices(include_blank=self.blank, blank_choice=BLANK_CHOICE_NONE) |
|---|
| 170 |
params['ul_class'] = get_ul_class(self.radio_admin) |
|---|
| 171 |
else: |
|---|
| 172 |
field_objs = [formfields.SelectField] |
|---|
| 173 |
params['choices'] = self.get_choices() |
|---|
| 174 |
else: |
|---|
| 175 |
field_objs = self.get_manipulator_field_objs() |
|---|
| 176 |
|
|---|
| 177 |
# Add the "unique" validator(s). |
|---|
| 178 |
for field_name_list in opts.unique_together: |
|---|
| 179 |
if field_name_list[0] == self.name: |
|---|
| 180 |
params['validator_list'].append(getattr(manipulator, 'isUnique%s' % '_'.join(field_name_list))) |
|---|
| 181 |
|
|---|
| 182 |
# Add the "unique for..." validator(s). |
|---|
| 183 |
if self.unique_for_date: |
|---|
| 184 |
params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_date))) |
|---|
| 185 |
if self.unique_for_month: |
|---|
| 186 |
params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_month))) |
|---|
| 187 |
if self.unique_for_year: |
|---|
| 188 |
params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_year))) |
|---|
| 189 |
if self.unique or (self.primary_key and not rel): |
|---|
| 190 |
params['validator_list'].append(curry(manipulator_validator_unique, self, opts, manipulator)) |
|---|
| 191 |
|
|---|
| 192 |
# Only add is_required=True if the field cannot be blank. Primary keys |
|---|
| 193 |
# are a special case, and fields in a related context should set this |
|---|
| 194 |
# as False, because they'll be caught by a separate validator -- |
|---|
| 195 |
# RequiredIfOtherFieldGiven. |
|---|
| 196 |
params['is_required'] = not self.blank and not self.primary_key and not rel |
|---|
| 197 |
|
|---|
| 198 |
# If this field is in a related context, check whether any other fields |
|---|
| 199 |
# in the related object have core=True. If so, add a validator -- |
|---|
| 200 |
# RequiredIfOtherFieldsGiven -- to this FormField. |
|---|
| 201 |
if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, FileField): |
|---|
| 202 |
# First, get the core fields, if any. |
|---|
| 203 |
core_field_names = [] |
|---|
| 204 |
for f in opts.fields: |
|---|
| 205 |
if f.core and f != self: |
|---|
| 206 |
core_field_names.extend(f.get_manipulator_field_names(name_prefix)) |
|---|
| 207 |
# Now, if there are any, add the validator to this FormField. |
|---|
| 208 |
if core_field_names: |
|---|
| 209 |
params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, "This field is required.")) |
|---|
| 210 |
|
|---|
| 211 |
# BooleanFields (CheckboxFields) are a special case. They don't take |
|---|
| 212 |
# is_required or validator_list. |
|---|
| 213 |
if isinstance(self, BooleanField): |
|---|
| 214 |
del params['validator_list'], params['is_required'] |
|---|
| 215 |
|
|---|
| 216 |
# Finally, add the field_names. |
|---|
| 217 |
field_names = self.get_manipulator_field_names(name_prefix) |
|---|
| 218 |
return [man(field_name=field_names[i], **params) for i, man in enumerate(field_objs)] |
|---|
| 219 |
|
|---|
| 220 |
def get_manipulator_new_data(self, new_data, rel=False): |
|---|
| 221 |
""" |
|---|
| 222 |
Given the full new_data dictionary (from the manipulator), returns this |
|---|
| 223 |
field's data. |
|---|
| 224 |
""" |
|---|
| 225 |
if rel: |
|---|
| 226 |
return new_data.get(self.name, [self.get_default()])[0] |
|---|
| 227 |
else: |
|---|
| 228 |
val = new_data.get(self.name, self.get_default()) |
|---|
| 229 |
if not self.empty_strings_allowed and val == '' and self.null: |
|---|
| 230 |
val = None |
|---|
| 231 |
return val |
|---|
| 232 |
|
|---|
| 233 |
def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): |
|---|
| 234 |
"Returns a list of tuples used as SelectField choices for this field." |
|---|
| 235 |
first_choice = include_blank and blank_choice or [] |
|---|
| 236 |
if self.choices: |
|---|
| 237 |
return first_choice + list(self.choices) |
|---|
| 238 |
rel_obj = self.rel.to |
|---|
| 239 |
return first_choice + [(getattr(x, rel_obj.pk.name), repr(x)) for x in rel_obj.get_model_module().get_list(**self.rel.limit_choices_to)] |
|---|
| 240 |
|
|---|
| 241 |
class AutoField(Field): |
|---|
| 242 |
empty_strings_allowed = False |
|---|
| 243 |
def __init__(self, *args, **kwargs): |
|---|
| 244 |
assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__ |
|---|
| 245 |
Field.__init__(self, *args, **kwargs) |
|---|
| 246 |
|
|---|
| 247 |
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False): |
|---|
| 248 |
if not rel: |
|---|
| 249 |
return [] # Don't add a FormField unless it's in a related context. |
|---|
| 250 |
return Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel) |
|---|
| 251 |
|
|---|
| 252 |
def get_manipulator_field_objs(self): |
|---|
| 253 |
return [formfields.HiddenField] |
|---|
| 254 |
|
|---|
| 255 |
def get_manipulator_new_data(self, new_data, rel=False): |
|---|
| 256 |
if not rel: |
|---|
| 257 |
return None |
|---|
| 258 |
return Field.get_manipulator_new_data(self, new_data, rel) |
|---|
| 259 |
|
|---|
| 260 |
class BooleanField(Field): |
|---|
| 261 |
def __init__(self, *args, **kwargs): |
|---|
| 262 |
kwargs['blank'] = True |
|---|
| 263 |
Field.__init__(self, *args, **kwargs) |
|---|
| 264 |
|
|---|
| 265 |
def get_db_prep_lookup(self, lookup_type, value): |
|---|
| 266 |
if db.DATABASE_ENGINE == 'oracle': |
|---|
| 267 |
if value == 'True': |
|---|
| 268 |
value = 1 |
|---|
| 269 |
elif value == 'False': |
|---|
| 270 |
value = 0 |
|---|
| 271 |
return Field.get_db_prep_lookup(self, lookup_type, value) |
|---|
| 272 |
|
|---|
| 273 |
def get_manipulator_field_objs(self): |
|---|
| 274 |
return [formfields.CheckboxField] |
|---|
| 275 |
|
|---|
| 276 |
class CharField(Field): |
|---|
| 277 |
def get_manipulator_field_objs(self): |
|---|
| 278 |
return [formfields.TextField] |
|---|
| 279 |
|
|---|
| 280 |
class CommaSeparatedIntegerField(CharField): |
|---|
| 281 |
def get_manipulator_field_objs(self): |
|---|
| 282 |
return [formfields.CommaSeparatedIntegerField] |
|---|
| 283 |
|
|---|
| 284 |
class DateField(Field): |
|---|
| 285 |
empty_strings_allowed = False |
|---|
| 286 |
def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): |
|---|
| 287 |
self.auto_now, self.auto_now_add = auto_now, auto_now_add |
|---|
| 288 |
if auto_now or auto_now_add: |
|---|
| 289 |
kwargs['editable'] = False |
|---|
| 290 |
Field.__init__(self, name, verbose_name, **kwargs) |
|---|
| 291 |
|
|---|
| 292 |
def get_db_prep_lookup(self, lookup_type, value): |
|---|
| 293 |
if lookup_type == 'range': |
|---|
| 294 |
value = [str(v) for v in value] |
|---|
| 295 |
else: |
|---|
| 296 |
value = str(value) |
|---|
| 297 |
return Field.get_db_prep_lookup(self, lookup_type, value) |
|---|
| 298 |
|
|---|
| 299 |
def pre_save(self, value, add): |
|---|
| 300 |
if self.auto_now or (self.auto_now_add and add): |
|---|
| 301 |
return datetime.datetime.now() |
|---|
| 302 |
return value |
|---|
| 303 |
|
|---|
| 304 |
def get_db_prep_save(self, value): |
|---|
| 305 |
# Casts dates into string format for entry into database. |
|---|
| 306 |
if value is not None: |
|---|
| 307 |
if db.DATABASE_ENGINE != 'oracle': |
|---|
| 308 |
#Oracle does not need a string conversion |
|---|
| 309 |
value = value.strftime('%Y-%m-%d') |
|---|
| 310 |
return Field.get_db_prep_save(self, value) |
|---|
| 311 |
|
|---|
| 312 |
def get_manipulator_field_objs(self): |
|---|
| 313 |
return [formfields.DateField] |
|---|
| 314 |
|
|---|
| 315 |
class DateTimeField(DateField): |
|---|
| 316 |
def get_db_prep_save(self, value): |
|---|
| 317 |
# Casts dates into string format for entry into database. |
|---|
| 318 |
if value is not None: |
|---|
| 319 |
if db.DATABASE_ENGINE != 'oracle': |
|---|
| 320 |
#Oracle does not need a string conversion |
|---|
| 321 |
value = value.strftime('%Y-%m-%d %H:%M:%S') |
|---|
| 322 |
return Field.get_db_prep_save(self, value) |
|---|
| 323 |
|
|---|
| 324 |
def get_manipulator_field_objs(self): |
|---|
| 325 |
return [formfields.DateField, formfields.TimeField] |
|---|
| 326 |
|
|---|
| 327 |
def get_manipulator_field_names(self, name_prefix): |
|---|
| 328 |
return [name_prefix + self.name + '_date', name_prefix + self.name + '_time'] |
|---|
| 329 |
|
|---|
| 330 |
def get_manipulator_new_data(self, new_data, rel=False): |
|---|
| 331 |
date_field, time_field = self.get_manipulator_field_names('') |
|---|
| 332 |
if rel: |
|---|
| 333 |
d = new_data.get(date_field, [None])[0] |
|---|
| 334 |
t = new_data.get(time_field, [None])[0] |
|---|
| 335 |
else: |
|---|
| 336 |
d = new_data.get(date_field, None) |
|---|
| 337 |
t = new_data.get(time_field, None) |
|---|
| 338 |
if d is not None and t is not None: |
|---|
| 339 |
return datetime.datetime.combine(d, t) |
|---|
| 340 |
return self.get_default() |
|---|
| 341 |
|
|---|
| 342 |
class EmailField(Field): |
|---|
| 343 |
def get_manipulator_field_objs(self): |
|---|
| 344 |
return [formfields.EmailField] |
|---|
| 345 |
|
|---|
| 346 |
class FileField(Field): |
|---|
| 347 |
def __init__(self, name, verbose_name=None, upload_to='', **kwargs): |
|---|
| 348 |
self.upload_to = upload_to |
|---|
| 349 |
Field.__init__(self, name, verbose_name, **kwargs) |
|---|
| 350 |
|
|---|
| 351 |
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False): |
|---|
| 352 |
field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel) |
|---|
| 353 |
|
|---|
| 354 |
if not self.blank: |
|---|
| 355 |
if rel: |
|---|
| 356 |
# This validator makes sure FileFields work in a related context. |
|---|
| 357 |
class RequiredFileField: |
|---|
| 358 |
def __init__(self, other_field_names, other_file_field_name): |
|---|
| 359 |
self.other_field_names = other_field_names |
|---|
| 360 |
self.other_file_field_name = other_file_field_name |
|---|
| 361 |
self.always_test = True |
|---|
| 362 |
def __call__(self, field_data, all_data): |
|---|
| 363 |
if not all_data.get(self.other_file_field_name, False): |
|---|
| 364 |
c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, "This field is required.") |
|---|
| 365 |
c(field_data, all_data) |
|---|
| 366 |
# First, get the core fields, if any. |
|---|
| 367 |
core_field_names = [] |
|---|
| 368 |
for f in opts.fields: |
|---|
| 369 |
if f.core and f != self: |
|---|
| 370 |
core_field_names.extend(f.get_manipulator_field_names(name_prefix)) |
|---|
| 371 |
# Now, if there are any, add the validator to this FormField. |
|---|
| 372 |
if core_field_names: |
|---|
| 373 |
field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) |
|---|
| 374 |
else: |
|---|
| 375 |
v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, "This field is required.") |
|---|
| 376 |
v.always_test = True |
|---|
| 377 |
field_list[0].validator_list.append(v) |
|---|
| 378 |
field_list[0].is_required = field_list[1].is_required = False |
|---|
| 379 |
|
|---|
| 380 |
# If the raw path is passed in, validate it's under the MEDIA_ROOT. |
|---|
| 381 |
def isWithinMediaRoot(field_data, all_data): |
|---|
| 382 |
f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) |
|---|
| 383 |
if not f.startswith(os.path.normpath(settings.MEDIA_ROOT)): |
|---|
| 384 |
raise validators.ValidationError, "Enter a valid filename." |
|---|
| 385 |
field_list[1].validator_list.append(isWithinMediaRoot) |
|---|
| 386 |
return field_list |
|---|
| 387 |
|
|---|
| 388 |
def get_manipulator_field_objs(self): |
|---|
| 389 |
return [formfields.FileUploadField, formfields.HiddenField] |
|---|
| 390 |
|
|---|
| 391 |
def get_manipulator_field_names(self, name_prefix): |
|---|
| 392 |
return [name_prefix + self.name + '_file', name_prefix + self.name] |
|---|
| 393 |
|
|---|
| 394 |
def save_file(self, new_data, new_object, original_object, change, rel): |
|---|
| 395 |
upload_field_name = self.get_manipulator_field_names('')[0] |
|---|
| 396 |
if new_data.get(upload_field_name, False): |
|---|
| 397 |
if rel: |
|---|
| 398 |
getattr(new_object, 'save_%s_file' % self.name)(new_data[upload_field_name][0]["filename"], new_data[upload_field_name][0]["content"]) |
|---|
| 399 |
else: |
|---|
| 400 |
getattr(new_object, 'save_%s_file' % self.name)(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"]) |
|---|
| 401 |
|
|---|
| 402 |
def get_directory_name(self): |
|---|
| 403 |
return os.path.normpath(datetime.datetime.now().strftime(self.upload_to)) |
|---|
| 404 |
|
|---|
| 405 |
def get_filename(self, filename): |
|---|
| 406 |
from django.utils.text import get_valid_filename |
|---|
| 407 |
f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename))) |
|---|
| 408 |
return os.path.normpath(f) |
|---|
| 409 |
|
|---|
| 410 |
class FloatField(Field): |
|---|
| 411 |
empty_strings_allowed = False |
|---|
| 412 |
def __init__(self, name, verbose_name=None, max_digits=None, decimal_places=None, **kwargs): |
|---|
| 413 |
self.max_digits, self.decimal_places = max_digits, decimal_places |
|---|
| 414 |
Field.__init__(self, name, verbose_name, **kwargs) |
|---|
| 415 |
|
|---|
| 416 |
def get_manipulator_field_objs(self): |
|---|
| 417 |
return [curry(formfields.FloatField, max_digits=self.max_digits, decimal_places=self.decimal_places)] |
|---|
| 418 |
|
|---|
| 419 |
class ImageField(FileField): |
|---|
| 420 |
def __init__(self, name, verbose_name=None, width_field=None, height_field=None, **kwargs): |
|---|
| 421 |
self.width_field, self.height_field = width_field, height_field |
|---|
| 422 |
FileField.__init__(self, name, verbose_name, **kwargs) |
|---|
| 423 |
|
|---|
| 424 |
def get_manipulator_field_objs(self): |
|---|
| 425 |
return [formfields.ImageUploadField, formfields.HiddenField] |
|---|
| 426 |
|
|---|
| 427 |
def save_file(self, new_data, new_object, original_object, change, rel): |
|---|
| 428 |
FileField.save_file(self, new_data, new_object, original_object, change, rel) |
|---|
| 429 |
# If the image has height and/or width field(s) and they haven't |
|---|
| 430 |
# changed, set the width and/or height field(s) back to their original |
|---|
| 431 |
# values. |
|---|
| 432 |
if change and (self.width_field or self.height_field): |
|---|
| 433 |
if self.width_field: |
|---|
| 434 |
setattr(new_object, self.width_field, getattr(original_object, self.width_field)) |
|---|
| 435 |
if self.height_field: |
|---|
| 436 |
setattr(new_object, self.height_field, getattr(original_object, self.height_field)) |
|---|
| 437 |
new_object.save() |
|---|
| 438 |
|
|---|