便利なDjangoフィールド

私はサンクトペテルブルク州立大学でフルタイムのプログラマーとして働いており、最近の仕事は写真ビデオ制作部門(大学のテレビを始めた)の活動に同行することです。 部門の責任者がレポートを自動化するためにすべての人にBitrix24に登録するように要求するとすぐに、着信タスクを自動化することを考えました(実際、すべてが少し深くなり、目標は規律でしたが、それは投稿には適用されません)。



実際、私が最初にしたことは、写真とビデオの撮影のための申込書を用意することでした。 この時点で、フレームワークに関する私の知識は、部門の内部サーバーにリストするためのいくつかのビューに限定されていました。 鉄の形の主な困難は突然フィールドになりました-同時に、私は美しさをもたらし、ユーザーの入力エラーを保護したかったのです。 電話の入力フィールドと時間選択という2つのフィールドに特に興味がありました。 それらとスピーチについて。



電話の入力フィールドから始めます。 最初はHabrに目を向けてポストを見つけましが、私が見たものは、私にはあまりにも扱いにくいように思えました(電話をオペレーターに転送する必要があったためです)。 CharFieldを使用しても私の目標にはならないことに気付き、Djangoのドキュメントをざわめいて、さらにMultiValueFieldとMultiWidgetを見つけました(MultiValueFieldのみを使用すると、テキストを入力するための通常の文字列が生成されるため、意味がありません) 。 数分後、コードはカットの下で作成されました。





1)まず、必要なものをインポートします。

from django.forms import MultiValueField, CharField, ChoiceField, MultiWidget, TextInput, Select
      
      







2)次に、Widgetを定義します。PhoneWidgetの基本クラスはMultiWidgetです。

 class PhoneWidget(MultiWidget): def __init__(self, code_length=3, num_length=7, attrs=None): widgets = [TextInput(attrs={'size': code_length, 'maxlength': code_length}), TextInput(attrs={'size': num_length, 'maxlength': num_length})] super(PhoneWidget, self).__init__(widgets, attrs) def decompress(self, value): if value: return [value.code, value.number] else: return ['', '']
      
      





少し説明:

サンクトペテルブルクとロシア全土のモバイルの都市コードの長さは3文字で、電話自体は7です。しかし、両方のパラメーターが変更される可能性があるため、コンストラクターで私に適したデフォルト値を指定しました。

次に、code_length(コード長)およびnum_length(数値の長さ)パラメーターを使用して、入力フィールドの長さ(美しさのため)および文字数(エラー保護のため)に制限がある2つのウィジェット自体(フィールド表現と呼ぶことができると思います)の定義があります。



美しさために、別のメソッドformat_output()を追加しました

 def format_output(self, rendered_widgets): return '+7' + '(' + rendered_widgets[0] + ') - ' + rendered_widgets[1]
      
      





htmlで美しい書式設定を取得するため。



3)MultiValueFieldの基本クラスとしてフィールド自体を定義します。

 class PhoneField(MultiValueField): def __init__(self, code_length, num_length, *args, **kwargs): list_fields = [CharField(), CharField()] super(PhoneField, self).__init__(list_fields, widget=PhoneWidget(code_length, num_length), *args, **kwargs) def compress(self, values): return '+7' + values[0] + values[1] #,     
      
      





少し説明:

コンストラクターには、ウィジェットコンストラクターに渡すための同じパラメーターが含まれています。 そうでなければ、私が書いたように、テキストを入力するための通常の文字列を取得します。



4)結果として、フォームのフィールドを示します

 p_num = PhoneField() # \    : PhoneField(code_length=some_value, num_length=some_value)
      
      





そして、テンプレートに追加することにより

 {{ form.p_num.errors }} <label for="phone_num"> :</label> </br> {{ form.p_num }}
      
      





長さ3文字と7文字(または表示される文字数)の2つの美しいフィールドと、標準化してユーザーにプロンプ​​トを表示する国際コードが表示されます。



類推により、時間を入力するためのウィジェットとフィールドが作成されました。

 class TimeWidget(MultiWidget): def __init__(self, h_choices, m_choices, attrs=None): widgets = [Select(choices=h_choices), Select(choices=m_choices)] super(TimeWidget, self).__init__(widgets, attrs) def decompress(self, value): if value: return [value.hours, value.minutes] else: return ['', ''] class TimeField(MultiValueField): def __init__(self, h_choices, m_choices, *args, **kwargs): list_fields = [ChoiceField(), ChoiceField()] super(TimeField, self).__init__(list_fields, widget=TimeWidget(h_choices, m_choices),*args, **kwargs) def compress(self, values): return return values[0] + ':' + values[1] #      datetime
      
      





ユーザーが就業日の外の時間を表示するのを防ぎ、合理的な制限(24と60)を超えないように、パラメーターを選択して2つのリストを作成しました。



呼び出し:

 time = TimeField(h_choices=HOURS_CHOICES, m_choices=MINUTES_CHOICES)
      
      





また、パラメーター自体(Djangoのドキュメントによると、タプルのリストであり、フォームクラスの外部で定義されている必要があります):

 HOURS_CHOICES = [(str(x), x) for x in range(9, 21)] #      ,     MINUTES_CHOICES = [(1, 0), (2, 10), (3, 20), (4, 30), (5, 40), (6, 50),] #  -  ,  - .     .
      
      









フィールド間に記号区切り文字を挿入する方法を理解するだけです(たとえば、時間と分の間の ':')が、これには機能的な負荷はありません。 ただし、この問題を解決し、見つけた解決策とフィールドの他の例で投稿を補足しようとします。



UPD: format_output()メソッドは、あらゆる種類のきちんとした書式設定ブラケットを取得するために記述されています



All Articles