web-dev-qa-db-ja.com

カスタマイズ/削除Django=ボックスの空白オプションを選択

私はDjango 1.0.2を使用しています。モデルに裏打ちされたModelFormを作成しました。このモデルには、blank = FalseのForeignKeyがあります。WhenDjangoこのフォームのHTMLを生成し、ForeignKeyによって参照されるテーブルの各行に1つのオプションを持つ選択ボックスを作成し、リストの上部に値を持たない一連のダッシュとして表示するオプションも作成します。

<option value="">---------</option>

私が知りたいのは:

  1. 選択ボックスからこの自動生成オプションを削除する最もクリーンな方法は何ですか?
  2. それをカスタマイズする最もクリーンな方法は何ですか:

    <option value="">Select Item</option>
    

ソリューションを探していると、私は Djangoチケット465 に出会いました。これは、他の人にも同じ質問があり、Djangoのデフォルトの動作が変更された可能性があります。このチケットは1年以上前のものなので、これらのことを達成するためのよりクリーンな方法があるかもしれないと期待していました。

助けてくれてありがとう、

ジェフ

編集:ForeignKeyフィールドを次のように構成しました:

verb = models.ForeignKey(Verb, blank=False, default=get_default_verb)

これによりデフォルトが設定され、空/ダッシュオプションではなくなりますが、残念ながら私の質問のいずれも解決しないようです。つまり、空/ダッシュオプションはリストに表示されたままです。

71
jlpp

これはテストしていませんが、Djangoのコードの読み取りに基づいています here および here

class ThingForm(models.ModelForm):
  class Meta:
    model = Thing

  def __init__(self, *args, **kwargs):
    super(ThingForm, self).__init__(*args, **kwargs)
    self.fields['verb'].empty_label = None

[〜#〜] edit [〜#〜]:これは 文書化された ですが、必ずしも見る必要があるとは限りません自動生成されたModelFormを使用している場合は、ModelChoiceFieldの場合。

[〜#〜] edit [〜#〜]:jlppが彼の答えで述べているように、これは完全ではありません。 empty_label属性を変更した後のウィジェットの選択。それは少しハックなので、理解しやすいかもしれない他のオプションは、ModelChoiceField全体をオーバーライドすることです。

class ThingForm(models.ModelForm):
  verb = ModelChoiceField(Verb.objects.all(), empty_label=None)

  class Meta:
    model = Thing
85
Carl Meyer

ドキュメントから

モデルフィールドにblank = Falseと明示的なデフォルト値がある場合、空白の選択肢は含まれません(代わりにデフォルト値が最初に選択されます)。

デフォルトを設定すれば大丈夫です

34
zalew

Carlの答えをガイドとして、Djangoソースを数時間根ざした後、これは完全なソリューションだと思います。

  1. 空のオプションを削除するには(Carlの例を拡張):

    class ThingForm(models.ModelForm):
      class Meta:
        model = Thing
    
      def __init__(self, *args, **kwargs):
        super(ThingForm, self).__init__(*args, **kwargs)
        self.fields['verb'].empty_label = None
        # following line needed to refresh widget copy of choice list
        self.fields['verb'].widget.choices =
          self.fields['verb'].choices
    
  2. 空のオプションラベルをカスタマイズするには、基本的に同じです。

    class ThingForm(models.ModelForm):
      class Meta:
        model = Thing
    
      def __init__(self, *args, **kwargs):
        super(ThingForm, self).__init__(*args, **kwargs)
        self.fields['verb'].empty_label = "Select a Verb"
        # following line needed to refresh widget copy of choice list
        self.fields['verb'].widget.choices =
          self.fields['verb'].choices
    

このアプローチは、ModelChoiceFieldsがHTMLとしてレンダリングされるすべてのシナリオに適用されると思いますが、私は肯定的ではありません。これらのフィールドが初期化されると、選択がSelectウィジェットに渡されることがわかりました(Django.forms.fields.ChoiceField._set_choicesを参照)。初期化後にempty_labelを設定しても、選択ウィジェットの選択リストは更新されません。 Djangoに十分に精通していないため、これをバグと見なすべきかどうかを知ることができます。

22
jlpp

モデルでこれを使用できます:

class MyModel(models.Model):
    name = CharField('fieldname', max_length=10, default=None)

デフォルト=なしは答えです:D

注:Django 1.7でこれを試しました

19
Lu.nemec

Django 1.4に関しては、選択肢フィールドに「デフォルト」値と「blank = False」を設定するだけです。

class MyModel(models.Model):
    CHOICES = (
        (0, 'A'), 
        (1, 'B'),
    )
    choice_field = models.IntegerField(choices=CHOICES, blank=False, default=0)
8
ykhrustalev

あなたは管理者でこれを行うことができます:

formfield_overrides = {
    models.ForeignKey: {'empty_label': None},
}
5
holmes86

この問題の完全な議論と解決方法については、 こちら をご覧ください。

5

self.fields['xxx'].empty_value = Noneは、フィールドタイプがTypedChoiceFieldで、empty_labelプロパティ。

私たちがすべきことは、最初の選択肢を削除することです:

1 BaseForm自動検出TypedChoiceFieldを構築する場合

class BaseForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(BaseForm, self).__init__(*args, **kwargs)

        for field_name in self.fields:
            field = self.fields.get(field_name)
            if field and isinstance(field , forms.TypedChoiceField):
                field.choices = field.choices[1:]
            # code to process other Field
            # ....

class AddClientForm(BaseForm):
     pass

2.ごく少数のフォーム、使用できます:

class AddClientForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(AddClientForm, self).__init__(*args, **kwargs)
        self.fields['xxx'].choices = self.fields['xxx'].choices[1:]
4
Mithril

ForeignKeyフィールドの場合、モデルでdefault値を''に設定すると、空白のオプションが削除されます。

verb = models.ForeignKey(Verb, on_delete=models.CASCADE, default='')

CharFieldなどの他のフィールドでは、defaultNoneに設定できますが、Django 1.11のForeignKeyフィールドでは機能しません。

3
YPCrumble

私は今日これをいじくり回していて、ちょうど思いついた ward病なハック 気の利いたソリューション:

# Cowardly handle ModelChoiceField empty label
# we all hate that '-----' thing
class ModelChoiceField_init_hack(object):
    @property
    def empty_label(self):
        return self._empty_label

    @empty_label.setter
    def empty_label(self, value):
        self._empty_label = value
        if value and value.startswith('-'):
            self._empty_label = 'Select an option'
ModelChoiceField.__bases__ += (ModelChoiceField_init_hack,)

これで、デフォルトのModelChoiceField空のラベルを好きなものに微調整できます。 :-)

PS:ダウンボートの必要はありません。無害なサルのパッチは常に便利です。

2
emyller

Django=の最新バージョンの場合、最初の答えは次のようになります

class ThingForm(models.ModelForm):
class Meta:
 model = Thing

  def __init__(self, *args, **kwargs):
    self.base_fields['cargo'].empty_label = None
    super(ThingForm, self).__init__(*args, **kwargs)`
2
lwj0012

私は解決策を見つけます!!

ただし、ForeignKeyではありません:-)

たぶん私はあなたを助けることができます。 Djangoソースコードを見て、Django.forms.extras.widgets.SelecteDateWidget()でnone_valueというプロパティが(0、 '-----')と等しいことを発見したので、私のコードでこれをしました

class StudentForm(ModelForm):
    class Meta:
        this_year = int(datetime.datetime.today().strftime('%Y')) 
        birth_years = []
        years = []

        for year in range(this_year - 2, this_year + 3 ):
            years.append(year)
        for year in range(this_year - 60, this_year+2):
            birth_years.append(year)

        model = Student
        exclude = ['user', 'fullname']
        date_widget = SelectDateWidget(years=years)

        date_widget.__setattr__('none_value', (0, 'THERE WAS THAT "-----" NO THERES THIS:-)'))
        widgets = {
            'beginning': date_widget,
            'birth': SelectDateWidget(years=birth_years),
        }
1
user3002411

選択肢が外部キーで、何らかの基準に基づいて選択肢をフィルタリングするの場合、これはより複雑になります。このような場合、empty_labelを設定してから選択肢を再割り当てすると(ここでもフィルターを適用できます)、空のラベルは空白になります。

class ThingForm(models.ModelForm):

    class Meta:
    model = Thing

    def __init__(self, *args, **kwargs):
        super(ThingForm, self).__init__(*args, **kwargs)
        self.fields['verb'].empty_label = None
        self.fields['verb'].queryset=Verb.objects.all()

基本的に、initの下の最初の行は、ループまたはインラインループのあるフォームのすべてのフィールドに適用できます。

def __init__(self,user, *args, **kwargs):
    super(NewTicket, self).__init__(*args, **kwargs)
    for f in self.fields:
       self.fields[f].empty_label = None # or "Please Select" etc
0
Ibo

ここにはたくさんの素晴らしい答えがありますが、私はまだ実装に完全には満足していません。また、さまざまなソース(外部キー、選択肢)からウィジェットを選択すると、さまざまな動作が得られることにも少しイライラしています。

私は、選択フィールドalwaysに空白のオプションがあり、必要な場合は横に星が付いているデザインを使用していますまた、フォームが空のままの場合、フォームは検証されません。そうは言っても、TypedChoiceFieldsではないフィールドのempty_labelのみを適切にオーバーライドできます。

結果shouldは次のようになります。最初の結果は常にフィールドの名前です-私の場合、labelです。

select widget

これが私がやったことです。以下は、オーバーライドされた__init__私のフォームのメソッド:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    for _, field in self.fields.items():
        if hasattr(field, 'empty_label'):
            field.empty_label = field.label
        if isinstance(field, forms.TypedChoiceField):
            field.choices = [('', field.label)] + [choice for choice in field.choices if choice[0]]
0
Jamie Counsell

Django 1.7であるため、モデルフィールド定義の選択リストに値を追加することにより、空白値のラベルをカスタマイズできます。設定に関するドキュメントから フィールドの選択肢

デフォルトで空白= Falseがフィールドに設定されていない場合、「---------」を含むラベルが選択ボックスでレンダリングされます。この動作をオーバーライドするには、Noneを含む選択肢にTupleを追加します。例えば(なし、「表示する文字列」)。または、CharFieldのように、これが理にかなっている場合はNoneの代わりに空の文字列を使用できます。

Django=の異なるバージョンのドキュメントを確認し、これが added Django 1.7

0
Rebecca Koeser