0

特定のプロジェクトでよくあるのは、ユーザーが寸法 (幅/奥行き/高さ) をフィートとインチで入力する必要があるということです。その寸法で計算を実行する必要があるため、フィート/インチ (例: 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
4

2 に答える 2

2

ありがとう、お二人ともありがとう。これが私が思いついたものです(両方のアドバイスに基づいて)。繰り返しの点でより良いものにするためにデータ型の定義に取り組みますが、それまでの間、これはうまくいきます...(私はとても近かったのに、とても遠かった...)皆さんは素晴らしいです。ありがとう。

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 FtInFormField(forms.Field):
        def clean(self,value):
                super(FtInFormField, 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 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)))

        def formfield(self, **kwargs):
                defaults = {'form_class': FtInFormField}
                defaults.update(kwargs)
                return super(FtInField,self).formfield(**defaults)

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):

        class Meta:
                model = ProductClass

class ProductClassAdmin(admin.ModelAdmin):
        form = ProductClassForm
于 2009-12-19T00:40:10.323 に答える
0

重複を避けるために、おそらくフィートとインチの解析を処理するデータ型クラスを実装する必要があります。これにより、他のコードが大幅に簡素化されるはずです。

次に、モデル フィールドとフォーム フィールドを作成する必要があります。これらは 2 つの完全に別個のコンポーネントであることに注意してください。(多かれ少なかれすでに行っていますが、これは完全を期すためのものです)

さて、私が質問を正しく読んでいれば、モデル フィールドのデフォルト フォーム フィールドを設定したいと思うでしょう。これを容易にするために、モデル フィールド クラスに formfield() 関数を実装します。参照:ジャンゴのドキュメント

于 2009-12-18T22:02:35.833 に答える