Source code for lighty.db.fields

'''All fields described
'''
import lighty.validators

from .functor import BaseField, NumericField, SequenceField


[docs]def add_validator(validator, options): '''Helper function for adding validator into the validator's list inside options dictionary. Written to make some field types constructor shorter. ''' if 'validators' in options: if isinstance(options['validators'], list): options['validators'].append(validator) else: options['validators'] += (validator, ) else: options['validators'] = (validator, ) return options
[docs]class Field(BaseField): '''Base field class. Declares basic methods an fields for all the field classes and fields ''' __slots__ = ('name', 'model', 'verbose_name', 'primary_key', 'db_index', 'unique', 'blank', 'null', 'choices', 'default', 'editable', 'error_messages', 'validators', 'help_text', 'db_column', 'db_tablespace', 'unique_for_date', 'unique_for_month', 'unique_for_year', ) model = None 'Model contains field' name = None 'Field name' verbose_name = name 'human readable field name' help_text = name 'field detailed description' editable = False 'check is field value can be changed' default = None 'default field value' choices = None 'list of values available for this field' blank = False 'is field can be empty on model saving' null = False 'is field can be None on model saving' error_messages = {} 'error messages for validations' validators = () '''list of the validators used to check field value before store it into the datastore''' primary_key = False 'is field would be a primary key' db_index = False 'is field a part of database index' db_column = name 'name of the field inside database' db_tablespace = False 'can be used to set additional datastorage parameter' unique = False 'add checking for unique value' unique_for_date = False 'check is field value unique for some date' unique_for_month = False 'check is field value unique for month' unique_for_year = False 'check if field value unique for year' def __init__(self, verbose_name=None, primary_key=False, db_index=False, unique=False, blank=False, null=False, choices=None, default=None, editable=True, error_messages={}, validators=(), help_text="", db_column=None, db_tablespace=False, unique_for_date=False, unique_for_month=False, unique_for_year=False): '''Create new Field instance Args: verbose_name: human readable field name primary_key: is field would be a primary key db_index: is field a part of database index unique: add checking for unique value blank: is field can be empty on model saving null: it field can be None on model saving choices: list of values available for this field default: default value editable: check is value can be changed error_messages: error messages for validations validators: list of validators used to check field value before store it into database help_text: field description db_column: name of the field inside database db_tablespace: can be used to set additional datastorage parameter unique_for_date: check is field value unique for some date unique_for_month: check is field value unique for month unique_for_year: check if field value unique for year ''' self.null = null self.blank = blank self.choices = choices self.default = default self.editable = editable self.db_column = db_column self.db_tablespace = db_tablespace self.db_index = db_index self.primary_key = primary_key self.help_text = help_text self.verbose_name = verbose_name self.error_messages = error_messages # Add additional choice if needed if choices is not None: validators += (lighty.validators.ChoicesValidator(choices),) self.validators = validators # Unique params if unique: self.unique = True unique_for_date = False unique_for_month = False unique_for_year = False else: self.unique = False if unique_for_date: self.unique_for_date = unique_for_date self.unique_for_month = False self.unique_for_year = False else: self.unique_for_date = False if unique_for_month: self.unique_for_month = unique_for_month self.unique_for_year = False else: self.unique_for_month = False self.unique_for_year = unique_for_year def __config__(self, model_name, field_name): """Configure field with model-depended paramenters Args: model_name: model class name field_name: name of this field """ self.model = model_name self.name = field_name
[docs] def get_value_for_datastore(self, model): """Get value prepared for saving in datastore Args: model: model instance to take value from """ return model.__dict__[self.name]
[docs] def make_value_from_datastore(self, value): """Create object from value was taken from datastore """ return value
def __str__(self): '''Get string representation ''' return self.model + '.' + self.name
[docs]class IntegerField(Field, NumericField): '''An integer. The admin represents this as an <input type="text"> (a single-line input). ''' pass
[docs]class PositiveIntegerField(IntegerField): '''Like an IntegerField, but must be positive. ''' def __init__(self, **options): '''Create new field. Adds validator that checks value to be greater than 0 into the validator's list ''' options = add_validator(lighty.validators.MinValueValidator(1), options) super(PositiveIntegerField, self).__init__(**options)
[docs]class AutoField(IntegerField): '''An IntegerField that automatically increments according to available IDs. You usually won't need to use this directly; a primary key field will automatically be added to your model if you don't specify otherwise. See Automatic primary key fields. ''' pass
[docs]class FloatField(Field, NumericField): '''A floating-point number represented in Python by a float instance. The admin represents this as an <input type="text"> (a single-line input). ''' pass
[docs]class DecimalField(Field, NumericField): '''A fixed-precision decimal number, represented in Python by a Decimal instance. The admin represents this as an <input type="text"> (a single-line input). ''' def __init__(self, max_digits=None, decimal_places=None, **options): '''Create new fixed-precision decimal number Args: max_digits: The maximum number of digits allowed in the number decimal_places: The number of decimal places to store with the number ''' self.max_digits super(DecimalField, self).__init__(**options)
[docs]class BooleanField(Field): '''A true/false field The admin represents this as a checkbox ''' pass
[docs]class NullBooleanField(BooleanField): '''Like a BooleanField, but allows NULL as one of the options. Use this instead of a BooleanField with null=True. The admin represents this as a <select> box with "Unknown", "Yes" and "No" choices. ''' def __init__(self, **options): '''Create new BooleanField field with null=True ''' options['null'] = True super(NullBooleanField, self).__init__(**options)
[docs]class CharField(Field, SequenceField): '''A string field, for small- to large-sized strings. For large amounts of text, use TextField. The admin represents this as an <input type="text"> (a single-line input). ''' def __init__(self, max_length=None, **options): '''Create new CharField with one extra required argument: Args: max_length: The maximum length (in characters) of the field. The max_length is enforced at the database level and in validation. ''' # Process max_length option if max_length is None: max_length = 255 self.max_length = max_length # Add MaxLengthValidator options = add_validator( lighty.validators.MaxLengthValidator(max_length), options) # Then create usual field super(CharField, self).__init__(**options)
[docs]class EmailField(CharField): '''A CharField that checks that the value is a valid e-mail address. ''' def __init__(self, max_length=75, **options): '''Create CharField that checks that the value is a valid e-mail address. ''' options = add_validator(lighty.validators.validate_email, options) super(EmailField, self).__init__(max_length, **options)
[docs]class URLField(CharField): '''A CharField for a URL. The admin represents this as an <input type="text"> (a single-line input). ''' def __init__(self, verify_exists=True, max_length=200, **options): '''Create new CharField to store URL Args: verify_exists: If True (the default), the URL given will be checked for existence (i.e., the URL actually loads and doesn't give a 404 response). Note that when you're using the single-threaded development server, validating a URL being served by the same server will hang. This should not be a problem for multithreaded servers. max_length: Like all CharField subclasses, URLField takes the optional max_length, a default of 200 is used. ''' options = add_validator( lighty.validators.URLValidator(verify_exists=verify_exists), options) super(URLField, self).__init__(max_length, **options)
[docs]class IPAddressField(Field): '''An IP address, in string format (e.g. "192.0.2.30"). The admin represents this as an <input type="text"> (a single-line input). ''' def __init__(self, **options): '''Create Field with addition validation for store IP address ''' options = add_validator(lighty.validators.validate_ipv4_address, options) super(IPAddressField, self).__init__(**options)
[docs]class SlugField(CharField): '''Slug is a newspaper term. A slug is a short label for something, containing only letters, numbers, underscores or hyphens. They're generally used in URLs. Implies setting Field.db_index to True. It is often useful to automatically prepopulate a SlugField based on the value of some other value. You can do this automatically in the admin using prepopulated_fields. ''' def __init__(self, max_length=50, **options): '''Create new CharField field with additional validator for slug Like a CharField, you can specify max_length (read the note about database portability and max_length in that section, too). If max_length is not specified, SlugField will use a default length of 50. ''' options['unique'] = True options = add_validator(lighty.validators.validate_slug, options) super(SlugField, self).__init__(max_length, **options)
[docs]class DateField(Field, NumericField): '''A date, represented in Python by a datetime.date instance. ''' def __init__(self, auto_now=False, auto_now_add=False, **options): '''Create new DateField. Has a few extra, optional arguments Args: auto_now: Automatically set the field to now every time the object is saved. Useful for "last-modified" timestamps. Note that the current date is always used; it's not just a default value that you can override. auto_now_add: Automatically set the field to now when the object is first created. Useful for creation of timestamps. Note that the current date is always used; it's not just a default value that you can override. ''' self.auto_now = auto_now self.auto_now_add = auto_now_add super(DateField, self).__init__(**options) def get_value_for_datastore(self, model): if self.auto_now or (self.auto_now_add and not model.is_saved()): from datetime import date model.__dict__[self.name] = date.today() return model.__dict__[self.name].strptime("%Y-%m-%d") def make_value_from_datastore(self, value): from datetime import date return date.strptime(value, "%Y-%m-%d")
[docs]class DateTimeField(DateField, NumericField): '''A date and time, represented in Python by a datetime.datetime instance. Takes the same extra arguments as DateField. '''
[docs] def get_value_for_datastore(self, model): '''Prepare value to store it into datastore. Returns: string represents field value in format "%Y-%m-%d %H:%M:%S" ''' from datetime import datetime if self.auto_now or (self.auto_now_add and not model.is_saved()): model.__dict__[self.name] = datetime.now() return datetime.strftime(model.__dict__[self.name], "%Y-%m-%d %H:%M:%S")
[docs] def make_value_from_datastore(self, value): '''Create date from value taken from datastore Returns: parsed DateTime object ''' from datetime import datetime if isinstance(value, datetime): return value return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
[docs]class TimeField(DateField, NumericField): '''A time, represented in Python by a datetime.time instance. Accepts the same auto-population options as DateField. '''
[docs] def get_value_for_datastore(self, model): '''Prepare value to store it into datastore. Returns: string represents field value in format "%Y-%m-%d %H:%M:%S" ''' from time import gmtime, strftime if self.auto_now or (self.auto_now_add and not model.is_saved()): model.__dict__[self.name] = gmtime() return strftime("%H:%M:%S", model.__dict__[self.name])
[docs] def make_value_from_datastore(self, value): '''Create date from value taken from datastore Returns: parsed Time object ''' from time import strptime return strptime(value, "%H:%M:%S")
[docs]class TextField(Field, SequenceField): '''A large text field. The admin represents this as a <textarea> (a multi-line input). ''' pass # # TODO: # write code for FileField, FilePathField and ImageField # write code for ForeignKey, ManyToManyField, OneToOneField #
[docs]class ForeignKey(Field): """An object field can contains """ def __init__(self, model, **kwargs): """ """ super(ForeignKey, self).__init__(kwargs) self.model = model
[docs] def get_value_for_datastore(self, model): """Get object's key """ return model.__dict__[self.name].key()
[docs] def make_value_from_datastore(self, value): """Get object for key """ return self.model.get(value)