特定のプロジェクトでよくあるのは、ユーザーが寸法 (幅/奥行き/高さ) をフィートとインチで入力する必要があるということです。その寸法で計算を実行する必要があるため、フィート/インチ (例: 1'-10") で寸法を取り、次を使用して 10 進数としてデータベースに保存するカスタム フィールド タイプに取り組んでいます。入力を解析するための正規表現. フィールドは常にフィートインチとしてエンドユーザーに表示されます (最終的な目標は、オプションでメトリックで表示し、measure.py や geodjango とやり取りできるメソッドを作成することです)これまでのところ、DRY ではないことは間違いありませんが、それとは別に、フォーム レベルでの検証に問題があります.カスタム モデル フィールド自体は適切に機能します (私が見たものから)。フィールドを検証するために機能するフォームフィールドのクリーンメソッドを作成しました。私の質問は、そのフォーム フィールドをモデル フォームにフックして、すべての幅/深さ/高さフィールドで機能する方法です。モデルフォーム (a la self.fields['depth']...) での init のオーバーライドを考えているのですが、ここからどこに行けばよいのかよくわかりません...
DCML_PATTERN = re.compile(r'^(?P<feet>\d+)(?P<dec_inch>\.?\d*)\'?$')
FTIN_PATTERN = re.compile(r'^(?P<feet>\d+)\'?\s*-?\s*(?P<inch>[0-9]|10|11)?\"?$')
class FtInField(models.Field):
__metaclass__ = models.SubfieldBase
empty_strings_allowed = False
def db_type(self):
return 'double'
def get_internal_type(self):
return "FtInField"
def to_python(self,value):
if value is u'' or value is None:
return None
if isinstance(value, float):
m = FTDCML_PATTERN.match(str(value))
if m is None:
raise Exception('Must be an integer or decimal number')
feet = int(m.group('feet'))
dec_inch = float(m.group('dec_inch') or 0)
inch = dec_inch * 12
return "%d\'-%.0f\"" % (feet,inch)
return value
def get_db_prep_value(self,value):
if value is u'' or value is None:
return None
m = FTIN_PATTERN.match(value)
if m is None:
raise Exception('Must be in X\'-Y" Format')
feet = int(m.group('feet'))
inch = int(m.group('inch') or 0)
return (feet + (inch/float(12)))
class FtInField(forms.Field):
def clean(self,value):
super(FtInField, self).clean(value)
if value is u'' or value is None:
raise forms.ValidationError('Enter a dimension in X\'-Y" format')
m = FTIN_PATTERN.match(value)
if m is None:
raise forms.ValidationError('Must be in X\'-Y" Format')
feet = int(m.group('feet'))
inch = int(m.group('inch') or 0)
value = '%d\'-%.0f"' % (feet,inch)
return value
class ProductClass(models.Model):
productname = models.CharField('Product Name', max_length=60,blank=True)
depth = FtInField('Depth (Feet/Inches)')
width = FtInField('Width (Feet/Inches)')
height = FtInField('Height (Feet/Inches)')
class ProductClassForm(forms.ModelForm):
depth = FtInField()
width = FtInField()
height = FtInField()
class Meta:
model = ProductClass
class ProductClassAdmin(admin.ModelAdmin):
form = ProductClassForm