2006-05-02 09:31:56 +08:00
from django . db . models import signals
from django . dispatch import dispatcher
2005-08-02 05:29:52 +08:00
from django . conf import settings
2006-05-02 09:31:56 +08:00
from django . core import validators
2006-12-16 02:00:50 +08:00
from django import oldforms
2006-12-16 02:15:55 +08:00
from django import newforms as forms
2005-08-02 05:29:52 +08:00
from django . core . exceptions import ObjectDoesNotExist
2006-07-22 04:39:17 +08:00
from django . utils . functional import curry
2006-09-26 14:33:32 +08:00
from django . utils . itercompat import tee
2005-08-02 05:29:52 +08:00
from django . utils . text import capfirst
2006-07-01 11:51:03 +08:00
from django . utils . translation import gettext , gettext_lazy
2006-05-02 09:31:56 +08:00
import datetime , os , time
2005-08-02 05:29:52 +08:00
2006-03-01 11:51:55 +08:00
class NOT_PROVIDED :
pass
2005-08-02 05:29:52 +08:00
# Values for filter_interface.
HORIZONTAL , VERTICAL = 1 , 2
# The values to use for "blank" in SelectFields. Will be appended to the start of most "choices" lists.
BLANK_CHOICE_DASH = [ ( " " , " --------- " ) ]
BLANK_CHOICE_NONE = [ ( " " , " None " ) ]
# prepares a value for use in a LIKE query
2006-08-11 13:20:31 +08:00
prep_for_like_query = lambda x : str ( x ) . replace ( " \\ " , " \\ \\ " ) . replace ( " % " , " \ % " ) . replace ( " _ " , " \ _ " )
2005-08-02 05:29:52 +08:00
# returns the <ul> class for a given radio_admin value
get_ul_class = lambda x : ' radiolist %s ' % ( ( x == HORIZONTAL ) and ' inline ' or ' ' )
2006-05-02 09:31:56 +08:00
class FieldDoesNotExist ( Exception ) :
pass
2005-08-02 05:29:52 +08:00
def manipulator_validator_unique ( f , opts , self , field_data , all_data ) :
" Validates that the value is unique for this field. "
2006-05-02 09:31:56 +08:00
lookup_type = f . get_validator_unique_lookup_type ( )
2005-08-02 05:29:52 +08:00
try :
2006-05-02 09:31:56 +08:00
old_obj = self . manager . get ( * * { lookup_type : field_data } )
2005-08-02 05:29:52 +08:00
except ObjectDoesNotExist :
return
2006-05-02 09:31:56 +08:00
if getattr ( self , ' original_object ' , None ) and self . original_object . _get_pk_val ( ) == old_obj . _get_pk_val ( ) :
2005-08-02 05:29:52 +08:00
return
2006-05-02 09:31:56 +08:00
raise validators . ValidationError , gettext ( " %(optname)s with this %(fieldname)s already exists. " ) % { ' optname ' : capfirst ( opts . verbose_name ) , ' fieldname ' : f . verbose_name }
2005-11-10 07:37:41 +08:00
# A guide to Field parameters:
#
2006-05-02 09:31:56 +08:00
# * name: The name of the field specifed in the model.
2005-11-10 07:37:41 +08:00
# * attname: The attribute to use on the model object. This is the same as
# "name", except in the case of ForeignKeys, where "_id" is
# appended.
# * db_column: The db_column specified in the model (or None).
# * column: The database column for this field. This is the same as
# "attname", except if db_column is specified.
#
# Code that introspects values, or does other dynamic things, should use
# attname. For example, this gets the primary key value of object "obj":
#
# getattr(obj, opts.pk.attname)
2005-08-02 05:29:52 +08:00
class Field ( object ) :
# Designates whether empty strings fundamentally are allowed at the
# database level.
empty_strings_allowed = True
2005-08-26 06:51:30 +08:00
# Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0
def __init__ ( self , verbose_name = None , name = None , primary_key = False ,
2006-05-02 09:31:56 +08:00
maxlength = None , unique = False , blank = False , null = False , db_index = False ,
2005-08-02 05:29:52 +08:00
core = False , rel = None , default = NOT_PROVIDED , editable = True ,
prepopulate_from = None , unique_for_date = None , unique_for_month = None ,
unique_for_year = None , validator_list = None , choices = None , radio_admin = None ,
2005-08-26 06:51:30 +08:00
help_text = ' ' , db_column = None ) :
2005-08-02 05:29:52 +08:00
self . name = name
2006-05-02 09:31:56 +08:00
self . verbose_name = verbose_name
2005-08-02 05:29:52 +08:00
self . primary_key = primary_key
self . maxlength , self . unique = maxlength , unique
self . blank , self . null = blank , null
self . core , self . rel , self . default = core , rel , default
self . editable = editable
self . validator_list = validator_list or [ ]
self . prepopulate_from = prepopulate_from
self . unique_for_date , self . unique_for_month = unique_for_date , unique_for_month
self . unique_for_year = unique_for_year
2006-09-26 14:33:32 +08:00
self . _choices = choices or [ ]
2005-08-02 05:29:52 +08:00
self . radio_admin = radio_admin
self . help_text = help_text
2005-08-26 06:51:30 +08:00
self . db_column = db_column
2005-08-02 05:29:52 +08:00
# Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
2006-05-02 09:31:56 +08:00
self . db_index = db_index
2005-08-02 05:29:52 +08:00
2005-08-26 06:51:30 +08:00
# Increase the creation counter, and save our local copy.
self . creation_counter = Field . creation_counter
Field . creation_counter + = 1
2006-05-02 09:31:56 +08:00
def __cmp__ ( self , other ) :
# This is needed because bisect does not take a comparison function.
return cmp ( self . creation_counter , other . creation_counter )
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 .
"""
return value
def validate_full ( self , field_data , all_data ) :
"""
Returns a list of errors for this field . This is the main interface ,
as it encapsulates some basic validation logic used by all fields .
Subclasses should implement validate ( ) , not validate_full ( ) .
"""
if not self . blank and not field_data :
return [ gettext_lazy ( ' This field is required. ' ) ]
try :
self . validate ( field_data , all_data )
except validators . ValidationError , e :
return e . messages
return [ ]
def validate ( self , field_data , all_data ) :
"""
Raises validators . ValidationError if field_data has any errors .
Subclasses should override this to specify field - specific validation
logic . This method should assume field_data has already been converted
into the appropriate data type by Field . to_python ( ) .
"""
pass
def set_attributes_from_name ( self , name ) :
self . name = name
2005-11-10 07:37:41 +08:00
self . attname , self . column = self . get_attname_column ( )
2006-05-02 09:31:56 +08:00
self . verbose_name = self . verbose_name or ( name and name . replace ( ' _ ' , ' ' ) )
def contribute_to_class ( self , cls , name ) :
self . set_attributes_from_name ( name )
cls . _meta . add_field ( self )
if self . choices :
setattr ( cls , ' get_ %s _display ' % self . name , curry ( cls . _get_FIELD_display , field = self ) )
2005-08-26 06:51:30 +08:00
2006-05-02 09:31:56 +08:00
def get_attname ( self ) :
return self . name
2005-11-10 07:37:41 +08:00
def get_attname_column ( self ) :
2006-05-02 09:31:56 +08:00
attname = self . get_attname ( )
2005-11-10 07:37:41 +08:00
column = self . db_column or attname
return attname , column
2005-08-26 06:51:30 +08:00
def get_cache_name ( self ) :
return ' _ %s _cache ' % self . name
2005-09-29 07:08:47 +08:00
def get_internal_type ( self ) :
return self . __class__ . __name__
2006-05-30 01:08:58 +08:00
def pre_save ( self , model_instance , add ) :
2005-08-10 13:08:27 +08:00
" Returns field ' s value just before saving. "
2006-05-30 01:08:58 +08:00
return getattr ( model_instance , self . attname )
2005-08-02 05:29:52 +08:00
2005-08-10 11:12:37 +08:00
def get_db_prep_save ( self , value ) :
2005-08-02 05:29:52 +08:00
" Returns field ' s value prepared for saving into a database. "
return value
def get_db_prep_lookup ( self , lookup_type , value ) :
" Returns field ' s value prepared for database lookup. "
2006-07-01 13:41:48 +08:00
if lookup_type in ( ' exact ' , ' gt ' , ' gte ' , ' lt ' , ' lte ' , ' year ' , ' month ' , ' day ' , ' search ' ) :
2005-08-02 05:29:52 +08:00
return [ value ]
elif lookup_type in ( ' range ' , ' in ' ) :
return value
2005-12-05 02:54:44 +08:00
elif lookup_type in ( ' contains ' , ' icontains ' ) :
2005-08-02 05:29:52 +08:00
return [ " %% %s %% " % prep_for_like_query ( value ) ]
elif lookup_type == ' iexact ' :
return [ prep_for_like_query ( value ) ]
2005-12-05 02:54:44 +08:00
elif lookup_type in ( ' startswith ' , ' istartswith ' ) :
2005-08-02 05:29:52 +08:00
return [ " %s %% " % prep_for_like_query ( value ) ]
2005-12-05 02:54:44 +08:00
elif lookup_type in ( ' endswith ' , ' iendswith ' ) :
2005-08-02 05:29:52 +08:00
return [ " %% %s " % prep_for_like_query ( value ) ]
elif lookup_type == ' isnull ' :
return [ ]
raise TypeError , " Field has invalid lookup: %s " % lookup_type
def has_default ( self ) :
" Returns a boolean of whether this field has a default value. "
2006-03-01 11:51:55 +08:00
return self . default is not NOT_PROVIDED
2005-08-02 05:29:52 +08:00
def get_default ( self ) :
" Returns the default value for this field. "
2006-03-01 11:51:55 +08:00
if self . default is not NOT_PROVIDED :
2006-05-02 09:31:56 +08:00
if callable ( self . default ) :
return self . default ( )
2005-08-02 05:29:52 +08:00
return self . default
2005-11-26 05:20:09 +08:00
if not self . empty_strings_allowed or self . null :
2005-08-02 05:29:52 +08:00
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 ]
2006-05-02 09:31:56 +08:00
def prepare_field_objs_and_params ( self , manipulator , name_prefix ) :
2005-08-02 05:29:52 +08:00
params = { ' validator_list ' : self . validator_list [ : ] }
if self . maxlength and not self . choices : # Don't give SelectFields a maxlength parameter.
params [ ' maxlength ' ] = self . maxlength
2006-05-02 09:31:56 +08:00
if self . choices :
2005-08-02 05:29:52 +08:00
if self . radio_admin :
2006-12-16 02:00:50 +08:00
field_objs = [ oldforms . RadioSelectField ]
2005-08-02 05:29:52 +08:00
params [ ' ul_class ' ] = get_ul_class ( self . radio_admin )
else :
2006-12-16 02:00:50 +08:00
field_objs = [ oldforms . SelectField ]
2005-11-26 05:20:09 +08:00
params [ ' choices ' ] = self . get_choices_default ( )
2005-08-02 05:29:52 +08:00
else :
field_objs = self . get_manipulator_field_objs ( )
2006-05-02 09:31:56 +08:00
return ( field_objs , params )
def get_manipulator_fields ( self , opts , manipulator , change , name_prefix = ' ' , rel = False , follow = True ) :
"""
2006-12-16 02:00:50 +08:00
Returns a list of oldforms . FormField instances for this field . It
2006-05-02 09:31:56 +08:00
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 )
2005-08-02 05:29:52 +08:00
# 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 %s For %s ' % ( self . name , self . unique_for_date ) ) )
if self . unique_for_month :
params [ ' validator_list ' ] . append ( getattr ( manipulator , ' isUnique %s For %s ' % ( self . name , self . unique_for_month ) ) )
if self . unique_for_year :
params [ ' validator_list ' ] . append ( getattr ( manipulator , ' isUnique %s For %s ' % ( self . name , self . unique_for_year ) ) )
2005-08-11 03:32:38 +08:00
if self . unique or ( self . primary_key and not rel ) :
2005-08-02 05:29:52 +08:00
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
2006-05-02 09:31:56 +08:00
# BooleanFields (CheckboxFields) are a special case. They don't take
2006-07-28 08:13:10 +08:00
# is_required.
2006-05-02 09:31:56 +08:00
if isinstance ( self , BooleanField ) :
2006-07-28 08:13:10 +08:00
del params [ ' is_required ' ]
2006-05-02 09:31:56 +08:00
2005-08-02 05:29:52 +08:00
# 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 :
2005-11-25 10:37:57 +08:00
params [ ' validator_list ' ] . append ( validators . RequiredIfOtherFieldsGiven ( core_field_names , gettext_lazy ( " This field is required. " ) ) )
2005-08-02 05:29:52 +08:00
# 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 ) ]
2006-05-02 09:31:56 +08:00
def get_validator_unique_lookup_type ( self ) :
return ' %s __exact ' % self . name
2005-08-02 05:29:52 +08:00
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 ]
2006-05-02 09:31:56 +08:00
val = new_data . get ( self . name , self . get_default ( ) )
if not self . empty_strings_allowed and val == ' ' and self . null :
val = None
return val
2005-08-02 05:29:52 +08:00
def get_choices ( self , include_blank = True , blank_choice = BLANK_CHOICE_DASH ) :
" Returns a list of tuples used as SelectField choices for this field. "
first_choice = include_blank and blank_choice or [ ]
if self . choices :
return first_choice + list ( self . choices )
2006-05-02 09:31:56 +08:00
rel_model = self . rel . to
2006-08-01 22:20:01 +08:00
if hasattr ( self . rel , ' get_related_field ' ) :
lst = [ ( getattr ( x , self . rel . get_related_field ( ) . attname ) , str ( x ) ) for x in rel_model . _default_manager . complex_filter ( self . rel . limit_choices_to ) ]
else :
lst = [ ( x . _get_pk_val ( ) , str ( x ) ) for x in rel_model . _default_manager . complex_filter ( self . rel . limit_choices_to ) ]
return first_choice + lst
2005-11-26 05:20:09 +08:00
def get_choices_default ( self ) :
2006-05-02 09:31:56 +08:00
if self . radio_admin :
2005-11-26 05:20:09 +08:00
return self . get_choices ( include_blank = self . blank , blank_choice = BLANK_CHOICE_NONE )
else :
return self . get_choices ( )
def _get_val_from_obj ( self , obj ) :
if obj :
2006-05-02 09:31:56 +08:00
return getattr ( obj , self . attname )
2005-11-26 05:20:09 +08:00
else :
2006-05-02 09:31:56 +08:00
return self . get_default ( )
2005-11-26 05:20:09 +08:00
2005-12-09 10:15:54 +08:00
def flatten_data ( self , follow , obj = None ) :
2005-11-26 05:20:09 +08:00
"""
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 .
"""
return { self . attname : self . _get_val_from_obj ( obj ) }
def get_follow ( self , override = None ) :
if override != None :
return override
else :
return self . editable
2006-05-02 09:31:56 +08:00
def bind ( self , fieldmapping , original , bound_field_class ) :
2005-11-26 05:20:09 +08:00
return bound_field_class ( self , fieldmapping , original )
2005-08-02 05:29:52 +08:00
2006-09-26 14:33:32 +08:00
def _get_choices ( self ) :
if hasattr ( self . _choices , ' next ' ) :
choices , self . _choices = tee ( self . _choices )
return choices
else :
return self . _choices
choices = property ( _get_choices )
2006-12-15 13:46:11 +08:00
def formfield ( self ) :
" Returns a django.newforms.Field instance for this database Field. "
# TODO: This is just a temporary default during development.
2006-12-16 02:15:55 +08:00
return forms . CharField ( label = capfirst ( self . verbose_name ) )
2006-12-15 13:46:11 +08:00
2005-08-02 05:29:52 +08:00
class AutoField ( Field ) :
empty_strings_allowed = False
2005-08-10 13:08:27 +08:00
def __init__ ( self , * args , * * kwargs ) :
assert kwargs . get ( ' primary_key ' , False ) is True , " %s s must have primary_key=True. " % self . __class__ . __name__
2006-05-02 09:31:56 +08:00
kwargs [ ' blank ' ] = True
2005-08-10 13:08:27 +08:00
Field . __init__ ( self , * args , * * kwargs )
2006-05-02 09:31:56 +08:00
def to_python ( self , value ) :
if value is None :
return value
try :
return int ( value )
except ( TypeError , ValueError ) :
raise validators . ValidationError , gettext ( " This value must be an integer. " )
def get_manipulator_fields ( self , opts , manipulator , change , name_prefix = ' ' , rel = False , follow = True ) :
2005-08-02 05:29:52 +08:00
if not rel :
return [ ] # Don't add a FormField unless it's in a related context.
2006-05-02 09:31:56 +08:00
return Field . get_manipulator_fields ( self , opts , manipulator , change , name_prefix , rel , follow )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . HiddenField ]
2005-08-02 05:29:52 +08:00
def get_manipulator_new_data ( self , new_data , rel = False ) :
2006-05-02 09:31:56 +08:00
# Never going to be called
# Not in main change pages
# ignored in related context
2005-08-02 05:29:52 +08:00
if not rel :
return None
return Field . get_manipulator_new_data ( self , new_data , rel )
2006-05-02 09:31:56 +08:00
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 )
cls . _meta . has_auto_field = True
2005-08-02 05:29:52 +08:00
class BooleanField ( Field ) :
def __init__ ( self , * args , * * kwargs ) :
kwargs [ ' blank ' ] = True
Field . __init__ ( self , * args , * * kwargs )
2006-05-02 09:31:56 +08:00
def to_python ( self , value ) :
if value in ( True , False ) : return value
2006-09-26 08:36:04 +08:00
if value in ( ' t ' , ' True ' , ' 1 ' ) : return True
if value in ( ' f ' , ' False ' , ' 0 ' ) : return False
2006-05-02 09:31:56 +08:00
raise validators . ValidationError , gettext ( " This value must be either True or False. " )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . CheckboxField ]
2005-08-02 05:29:52 +08:00
class CharField ( Field ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . TextField ]
2006-05-02 09:31:56 +08:00
def to_python ( self , value ) :
if isinstance ( value , basestring ) :
return value
if value is None :
if self . null :
return value
else :
raise validators . ValidationError , gettext_lazy ( " This field cannot be null. " )
return str ( value )
2005-08-02 05:29:52 +08:00
2006-05-02 09:31:56 +08:00
# TODO: Maybe move this into contrib, because it's specialized.
2005-08-02 05:29:52 +08:00
class CommaSeparatedIntegerField ( CharField ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . CommaSeparatedIntegerField ]
2005-08-02 05:29:52 +08:00
class DateField ( Field ) :
empty_strings_allowed = False
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , auto_now = False , auto_now_add = False , * * kwargs ) :
2005-08-02 05:29:52 +08:00
self . auto_now , self . auto_now_add = auto_now , auto_now_add
2006-05-02 09:31:56 +08:00
#HACKs : auto_now_add/auto_now should be done as a default or a pre_save.
2005-08-02 05:29:52 +08:00
if auto_now or auto_now_add :
kwargs [ ' editable ' ] = False
2005-11-26 05:20:09 +08:00
kwargs [ ' blank ' ] = True
2005-08-26 06:51:30 +08:00
Field . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
2006-05-02 09:31:56 +08:00
def to_python ( self , value ) :
if isinstance ( value , datetime . datetime ) :
return value . date ( )
if isinstance ( value , datetime . date ) :
return value
validators . isValidANSIDate ( value , None )
2006-07-01 02:57:23 +08:00
try :
return datetime . date ( * time . strptime ( value , ' % Y- % m- %d ' ) [ : 3 ] )
except ValueError :
raise validators . ValidationError , gettext ( ' Enter a valid date in YYYY-MM-DD format. ' )
2006-05-02 09:31:56 +08:00
2005-08-02 05:29:52 +08:00
def get_db_prep_lookup ( self , lookup_type , value ) :
if lookup_type == ' range ' :
value = [ str ( v ) for v in value ]
2006-07-01 13:41:48 +08:00
elif lookup_type in ( ' exact ' , ' gt ' , ' gte ' , ' lt ' , ' lte ' ) and hasattr ( value , ' strftime ' ) :
2006-05-02 09:31:56 +08:00
value = value . strftime ( ' % Y- % m- %d ' )
2005-08-02 05:29:52 +08:00
else :
value = str ( value )
return Field . get_db_prep_lookup ( self , lookup_type , value )
2006-05-30 01:08:58 +08:00
def pre_save ( self , model_instance , add ) :
2005-08-10 11:50:46 +08:00
if self . auto_now or ( self . auto_now_add and add ) :
2006-05-30 01:08:58 +08:00
value = datetime . datetime . now ( )
setattr ( model_instance , self . attname , value )
return value
else :
return super ( DateField , self ) . pre_save ( model_instance , add )
2005-08-02 05:29:52 +08:00
2006-05-02 09:31:56 +08:00
def contribute_to_class ( self , cls , name ) :
super ( DateField , self ) . contribute_to_class ( cls , name )
if not self . null :
setattr ( cls , ' get_next_by_ %s ' % self . name ,
curry ( cls . _get_next_or_previous_by_FIELD , field = self , is_next = True ) )
setattr ( cls , ' get_previous_by_ %s ' % self . name ,
curry ( cls . _get_next_or_previous_by_FIELD , field = self , is_next = False ) )
2005-11-26 05:20:09 +08:00
# 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
2005-08-10 11:12:37 +08:00
def get_db_prep_save ( self , value ) :
2005-08-02 05:29:52 +08:00
# Casts dates into string format for entry into database.
2006-11-26 10:38:04 +08:00
if value is not None :
2005-08-02 05:29:52 +08:00
value = value . strftime ( ' % Y- % m- %d ' )
2005-08-10 11:12:37 +08:00
return Field . get_db_prep_save ( self , value )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . DateField ]
2005-08-02 05:29:52 +08:00
2005-11-26 05:20:09 +08:00
def flatten_data ( self , follow , obj = None ) :
val = self . _get_val_from_obj ( obj )
return { self . attname : ( val is not None and val . strftime ( " % Y- % m- %d " ) or ' ' ) }
2005-08-02 05:29:52 +08:00
class DateTimeField ( DateField ) :
2006-05-02 09:31:56 +08:00
def to_python ( self , value ) :
if isinstance ( value , datetime . datetime ) :
return value
if isinstance ( value , datetime . date ) :
return datetime . datetime ( value . year , value . month , value . day )
try : # Seconds are optional, so try converting seconds first.
return datetime . datetime ( * time . strptime ( value , ' % Y- % m- %d % H: % M: % S ' ) [ : 6 ] )
except ValueError :
try : # Try without seconds.
return datetime . datetime ( * time . strptime ( value , ' % Y- % m- %d % H: % M ' ) [ : 5 ] )
except ValueError : # Try without hour/minutes/seconds.
try :
return datetime . datetime ( * time . strptime ( value , ' % Y- % m- %d ' ) [ : 3 ] )
except ValueError :
raise validators . ValidationError , gettext ( ' Enter a valid date/time in YYYY-MM-DD HH:MM format. ' )
2005-08-10 11:12:37 +08:00
def get_db_prep_save ( self , value ) :
2005-08-02 05:29:52 +08:00
# Casts dates into string format for entry into database.
2006-11-26 10:38:04 +08:00
if value is not None :
2005-08-15 09:03:39 +08:00
# MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds.
2006-06-21 12:13:48 +08:00
if settings . DATABASE_ENGINE == ' mysql ' and hasattr ( value , ' microsecond ' ) :
2005-08-15 09:03:39 +08:00
value = value . replace ( microsecond = 0 )
2005-08-12 03:34:34 +08:00
value = str ( value )
2005-08-10 11:12:37 +08:00
return Field . get_db_prep_save ( self , value )
2005-08-02 05:29:52 +08:00
2006-05-02 09:31:56 +08:00
def get_db_prep_lookup ( self , lookup_type , value ) :
if lookup_type == ' range ' :
value = [ str ( v ) for v in value ]
else :
value = str ( value )
return Field . get_db_prep_lookup ( self , lookup_type , value )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . DateField , oldforms . TimeField ]
2005-08-02 05:29:52 +08:00
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 ( )
2005-11-26 05:20:09 +08:00
def flatten_data ( self , follow , obj = None ) :
val = self . _get_val_from_obj ( obj )
date_field , time_field = self . get_manipulator_field_names ( ' ' )
return { date_field : ( val is not None and val . strftime ( " % Y- % m- %d " ) or ' ' ) ,
time_field : ( val is not None and val . strftime ( " % H: % M: % S " ) or ' ' ) }
2006-05-02 09:31:56 +08:00
class EmailField ( CharField ) :
2005-11-21 06:41:41 +08:00
def __init__ ( self , * args , * * kwargs ) :
kwargs [ ' maxlength ' ] = 75
2006-05-02 09:31:56 +08:00
CharField . __init__ ( self , * args , * * kwargs )
2005-11-21 06:41:41 +08:00
def get_internal_type ( self ) :
return " CharField "
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . EmailField ]
2006-05-02 09:31:56 +08:00
def validate ( self , field_data , all_data ) :
validators . isValidEmail ( field_data , all_data )
2005-08-02 05:29:52 +08:00
class FileField ( Field ) :
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , upload_to = ' ' , * * kwargs ) :
2005-08-02 05:29:52 +08:00
self . upload_to = upload_to
2005-08-26 06:51:30 +08:00
Field . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
2006-05-02 09:31:56 +08:00
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 )
2005-08-02 05:29:52 +08:00
if not self . blank :
if rel :
# This validator makes sure FileFields work in a related context.
2006-06-08 13:00:13 +08:00
class RequiredFileField ( object ) :
2005-08-02 05:29:52 +08:00
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 ) :
2005-11-25 10:37:57 +08:00
c = validators . RequiredIfOtherFieldsGiven ( self . other_field_names , gettext_lazy ( " This field is required. " ) )
2005-08-02 05:29:52 +08:00
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 :
2005-11-25 10:37:57 +08:00
v = validators . RequiredIfOtherFieldNotGiven ( field_list [ 1 ] . field_name , gettext_lazy ( " This field is required. " ) )
2005-08-02 05:29:52 +08:00
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 ) )
2006-11-07 10:25:49 +08:00
if not f . startswith ( os . path . abspath ( os . path . normpath ( settings . MEDIA_ROOT ) ) ) :
2005-11-25 10:37:57 +08:00
raise validators . ValidationError , _ ( " Enter a valid filename. " )
2005-08-02 05:29:52 +08:00
field_list [ 1 ] . validator_list . append ( isWithinMediaRoot )
return field_list
2006-05-02 09:31:56 +08:00
def contribute_to_class ( self , cls , name ) :
super ( FileField , self ) . contribute_to_class ( cls , name )
setattr ( cls , ' get_ %s _filename ' % self . name , curry ( cls . _get_FIELD_filename , field = self ) )
setattr ( cls , ' get_ %s _url ' % self . name , curry ( cls . _get_FIELD_url , field = self ) )
setattr ( cls , ' get_ %s _size ' % self . name , curry ( cls . _get_FIELD_size , field = self ) )
setattr ( cls , ' save_ %s _file ' % self . name , lambda instance , filename , raw_contents : instance . _save_FIELD_file ( self , filename , raw_contents ) )
dispatcher . connect ( self . delete_file , signal = signals . post_delete , sender = cls )
def delete_file ( self , instance ) :
if getattr ( instance , self . attname ) :
file_name = getattr ( instance , ' get_ %s _filename ' % self . name ) ( )
# If the file exists and no other object of this type references it,
# delete it from the filesystem.
if os . path . exists ( file_name ) and \
not instance . __class__ . _default_manager . filter ( * * { ' %s __exact ' % self . name : getattr ( instance , self . attname ) } ) :
os . remove ( file_name )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . FileUploadField , oldforms . HiddenField ]
2005-08-02 05:29:52 +08:00
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 ) :
upload_field_name = self . get_manipulator_field_names ( ' ' ) [ 0 ]
if new_data . get ( upload_field_name , False ) :
2005-12-10 13:32:05 +08:00
func = getattr ( new_object , ' save_ %s _file ' % self . name )
2005-08-02 05:29:52 +08:00
if rel :
2005-12-10 13:32:05 +08:00
func ( new_data [ upload_field_name ] [ 0 ] [ " filename " ] , new_data [ upload_field_name ] [ 0 ] [ " content " ] )
2005-08-02 05:29:52 +08:00
else :
2005-12-10 13:32:05 +08:00
func ( new_data [ upload_field_name ] [ " filename " ] , new_data [ upload_field_name ] [ " content " ] )
2005-08-02 05:29:52 +08:00
def get_directory_name ( self ) :
return os . path . normpath ( datetime . datetime . now ( ) . strftime ( self . upload_to ) )
def get_filename ( self , filename ) :
from django . utils . text import get_valid_filename
f = os . path . join ( self . get_directory_name ( ) , get_valid_filename ( os . path . basename ( filename ) ) )
return os . path . normpath ( f )
2005-10-12 12:14:21 +08:00
class FilePathField ( Field ) :
def __init__ ( self , verbose_name = None , name = None , path = ' ' , match = None , recursive = False , * * kwargs ) :
self . path , self . match , self . recursive = path , match , recursive
Field . __init__ ( self , verbose_name , name , * * kwargs )
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ curry ( oldforms . FilePathField , path = self . path , match = self . match , recursive = self . recursive ) ]
2005-10-12 12:14:21 +08:00
2005-08-02 05:29:52 +08:00
class FloatField ( Field ) :
empty_strings_allowed = False
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , max_digits = None , decimal_places = None , * * kwargs ) :
2005-08-02 05:29:52 +08:00
self . max_digits , self . decimal_places = max_digits , decimal_places
2005-08-26 06:51:30 +08:00
Field . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ curry ( oldforms . FloatField , max_digits = self . max_digits , decimal_places = self . decimal_places ) ]
2005-08-02 05:29:52 +08:00
class ImageField ( FileField ) :
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , width_field = None , height_field = None , * * kwargs ) :
2005-08-02 05:29:52 +08:00
self . width_field , self . height_field = width_field , height_field
2005-08-26 06:51:30 +08:00
FileField . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . ImageUploadField , oldforms . HiddenField ]
2006-05-02 09:31:56 +08:00
def contribute_to_class ( self , cls , name ) :
super ( ImageField , self ) . contribute_to_class ( cls , name )
# Add get_BLAH_width and get_BLAH_height methods, but only if the
# image field doesn't have width and height cache fields.
if not self . width_field :
setattr ( cls , ' get_ %s _width ' % self . name , curry ( cls . _get_FIELD_width , field = self ) )
if not self . height_field :
setattr ( cls , ' get_ %s _height ' % self . name , curry ( cls . _get_FIELD_height , field = self ) )
2005-08-02 05:29:52 +08:00
def save_file ( self , new_data , new_object , original_object , change , rel ) :
FileField . save_file ( self , new_data , new_object , original_object , change , rel )
# If the image has height and/or width field(s) and they haven't
# changed, set the width and/or height field(s) back to their original
# values.
if change and ( self . width_field or self . height_field ) :
if self . width_field :
setattr ( new_object , self . width_field , getattr ( original_object , self . width_field ) )
if self . height_field :
setattr ( new_object , self . height_field , getattr ( original_object , self . height_field ) )
new_object . save ( )
class IntegerField ( Field ) :
empty_strings_allowed = False
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . IntegerField ]
2005-08-02 05:29:52 +08:00
class IPAddressField ( Field ) :
def __init__ ( self , * args , * * kwargs ) :
kwargs [ ' maxlength ' ] = 15
Field . __init__ ( self , * args , * * kwargs )
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . IPAddressField ]
2006-05-02 09:31:56 +08:00
def validate ( self , field_data , all_data ) :
validators . isValidIPAddress4 ( field_data , None )
2005-08-02 05:29:52 +08:00
class NullBooleanField ( Field ) :
def __init__ ( self , * args , * * kwargs ) :
kwargs [ ' null ' ] = True
Field . __init__ ( self , * args , * * kwargs )
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . NullBooleanField ]
2005-08-02 05:29:52 +08:00
class PhoneNumberField ( IntegerField ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . PhoneNumberField ]
2006-05-02 09:31:56 +08:00
def validate ( self , field_data , all_data ) :
validators . isValidPhone ( field_data , all_data )
2005-08-02 05:29:52 +08:00
class PositiveIntegerField ( IntegerField ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . PositiveIntegerField ]
2005-08-02 05:29:52 +08:00
class PositiveSmallIntegerField ( IntegerField ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . PositiveSmallIntegerField ]
2005-08-02 05:29:52 +08:00
class SlugField ( Field ) :
def __init__ ( self , * args , * * kwargs ) :
2006-02-18 02:15:07 +08:00
kwargs [ ' maxlength ' ] = kwargs . get ( ' maxlength ' , 50 )
2005-10-20 12:20:52 +08:00
kwargs . setdefault ( ' validator_list ' , [ ] ) . append ( validators . isSlug )
2005-08-02 05:29:52 +08:00
# Set db_index=True unless it's been set manually.
if not kwargs . has_key ( ' db_index ' ) :
kwargs [ ' db_index ' ] = True
Field . __init__ ( self , * args , * * kwargs )
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . TextField ]
2005-08-02 05:29:52 +08:00
class SmallIntegerField ( IntegerField ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . SmallIntegerField ]
2005-08-02 05:29:52 +08:00
class TextField ( Field ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . LargeTextField ]
2005-08-02 05:29:52 +08:00
class TimeField ( Field ) :
empty_strings_allowed = False
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , auto_now = False , auto_now_add = False , * * kwargs ) :
2006-05-02 09:31:56 +08:00
self . auto_now , self . auto_now_add = auto_now , auto_now_add
2005-08-02 05:29:52 +08:00
if auto_now or auto_now_add :
kwargs [ ' editable ' ] = False
2005-08-26 06:51:30 +08:00
Field . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
def get_db_prep_lookup ( self , lookup_type , value ) :
if lookup_type == ' range ' :
value = [ str ( v ) for v in value ]
else :
value = str ( value )
return Field . get_db_prep_lookup ( self , lookup_type , value )
2006-05-30 01:08:58 +08:00
def pre_save ( self , model_instance , add ) :
2005-08-10 11:50:46 +08:00
if self . auto_now or ( self . auto_now_add and add ) :
2006-05-30 01:08:58 +08:00
value = datetime . datetime . now ( ) . time ( )
setattr ( model_instance , self . attname , value )
return value
else :
return super ( TimeField , self ) . pre_save ( model_instance , add )
2005-08-02 05:29:52 +08:00
2005-08-10 11:12:37 +08:00
def get_db_prep_save ( self , value ) :
2005-08-02 05:29:52 +08:00
# Casts dates into string format for entry into database.
if value is not None :
2005-08-15 09:03:39 +08:00
# MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds.
if settings . DATABASE_ENGINE == ' mysql ' :
value = value . replace ( microsecond = 0 )
2005-08-12 03:34:34 +08:00
value = str ( value )
2005-08-10 11:12:37 +08:00
return Field . get_db_prep_save ( self , value )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . TimeField ]
2005-08-02 05:29:52 +08:00
2005-11-26 05:20:09 +08:00
def flatten_data ( self , follow , obj = None ) :
val = self . _get_val_from_obj ( obj )
return { self . attname : ( val is not None and val . strftime ( " % H: % M: % S " ) or ' ' ) }
2005-08-02 05:29:52 +08:00
class URLField ( Field ) :
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , verify_exists = True , * * kwargs ) :
2005-08-02 05:29:52 +08:00
if verify_exists :
kwargs . setdefault ( ' validator_list ' , [ ] ) . append ( validators . isExistingURL )
2005-08-26 06:51:30 +08:00
Field . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . URLField ]
2005-08-02 05:29:52 +08:00
class USStateField ( Field ) :
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . USStateField ]
2005-08-02 05:29:52 +08:00
2005-09-29 07:08:47 +08:00
class XMLField ( TextField ) :
2005-08-26 06:51:30 +08:00
def __init__ ( self , verbose_name = None , name = None , schema_path = None , * * kwargs ) :
2005-08-02 05:29:52 +08:00
self . schema_path = schema_path
2005-08-26 06:51:30 +08:00
Field . __init__ ( self , verbose_name , name , * * kwargs )
2005-08-02 05:29:52 +08:00
2005-09-29 07:08:47 +08:00
def get_internal_type ( self ) :
return " TextField "
2005-08-02 05:29:52 +08:00
def get_manipulator_field_objs ( self ) :
2006-12-16 02:00:50 +08:00
return [ curry ( oldforms . XMLLargeTextField , schema_path = self . schema_path ) ]
2005-08-02 05:29:52 +08:00
2006-05-02 09:31:56 +08:00
class OrderingField ( IntegerField ) :
empty_strings_allowed = False
def __init__ ( self , with_respect_to , * * kwargs ) :
self . wrt = with_respect_to
kwargs [ ' null ' ] = True
IntegerField . __init__ ( self , * * kwargs )
2005-11-26 05:20:09 +08:00
2006-05-02 09:31:56 +08:00
def get_internal_type ( self ) :
return " IntegerField "
2005-11-26 05:20:09 +08:00
2006-05-02 09:31:56 +08:00
def get_manipulator_fields ( self , opts , manipulator , change , name_prefix = ' ' , rel = False , follow = True ) :
2006-12-16 02:00:50 +08:00
return [ oldforms . HiddenField ( name_prefix + self . name ) ]