73 строки
2.4 KiB
Python
73 строки
2.4 KiB
Python
import re
|
|
|
|
from django.forms import fields
|
|
from django.db import models
|
|
from django.core import exceptions
|
|
|
|
from tower import ugettext as _
|
|
|
|
from amo.widgets import ColorWidget
|
|
|
|
|
|
class DecimalCharField(models.DecimalField):
|
|
"""Like the standard django DecimalField but stored in a varchar
|
|
|
|
In order to gracefully read crappy data, use nullify_invalid=True.
|
|
This will set the field's value to None rather than raising an exception
|
|
whenever a non-null, non-decimal string is read from a queryset.
|
|
|
|
However, use this option with caution as it also prevents exceptions
|
|
from being raised during model property assignment. This could allow you
|
|
to "successfuly" save a ton of data when all that is really written
|
|
is NULL. It might be best to combine this with the null=False option.
|
|
"""
|
|
|
|
description = 'Decimal number stored as a varchar'
|
|
__metaclass__ = models.SubfieldBase
|
|
|
|
def __init__(self, verbose_name=None, name=None, max_digits=None,
|
|
decimal_places=None, nullify_invalid=False, **kwargs):
|
|
self.nullify_invalid = nullify_invalid
|
|
kwargs['max_length'] = max_digits + 1
|
|
super(DecimalCharField, self).__init__(verbose_name, name,
|
|
max_digits=max_digits, decimal_places=decimal_places, **kwargs)
|
|
|
|
def get_internal_type(self):
|
|
return "CharField"
|
|
|
|
def to_python(self, value):
|
|
try:
|
|
return super(DecimalCharField, self).to_python(value)
|
|
except exceptions.ValidationError:
|
|
if self.nullify_invalid:
|
|
return None
|
|
else:
|
|
raise
|
|
|
|
def get_db_prep_save(self, value, connection, prepared=False):
|
|
if prepared:
|
|
return value
|
|
else:
|
|
return self.get_prep_value(value)
|
|
|
|
def get_prep_value(self, value):
|
|
if value is None:
|
|
return value
|
|
return self.format_number(value)
|
|
|
|
|
|
class ColorField(fields.CharField):
|
|
|
|
widget = ColorWidget
|
|
|
|
def __init__(self, max_length=7, min_length=None, *args, **kwargs):
|
|
super(ColorField, self).__init__(max_length, min_length, *args,
|
|
**kwargs)
|
|
|
|
def clean(self, value):
|
|
super(ColorField, self).clean(value)
|
|
if value and not re.match('^\#([0-9a-fA-F]{6})$', value):
|
|
raise exceptions.ValidationError(
|
|
_(u'This must be a valid hex color code, such as #000000.'))
|
|
return value
|