2010-09-09 112 views
9

我想爲我的表單中的所有字段設置TextInput Widget的類屬性爲一個值,而不必在Meta中列出它們:widgets = {....這可能嗎?如何爲Django ModelForm設置默認控件屬性?

謝謝。在所有的領域

class PrettyWidget(forms.TextInput): 
    class Media: 
     css = { 
      'all': ('pretty.css',) 
     } 

在您的形式使用新的部件:

回答

13

您可以覆蓋的構造,以修改所有的TextInput控件:

from django import forms 

class MyForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(MyForm, self).__init__(*args, **kwargs) 
     for name, field in self.fields.items(): 
      if field.widget.__class__ == forms.widgets.TextInput: 
       if 'class' in field.widget.attrs: 
        field.widget.attrs['class'] += ' my-class' 
       else: 
        field.widget.attrs.update({'class':'my-class'}) 
    class Meta: 
     model = MyModel 

可以嗎用裝飾器覆蓋init?另外,在attrs.update()之前應該有一個if語句,因爲我想設置一個默認值,而不是覆蓋可能已經存在的值。 - 凱文

未經測試,但我想你可以繼承自MyForm,如果你使用這很多。

+0

你可以用裝飾器重寫init嗎?另外,在attrs.update()之前應該有一個if語句,因爲我想設置一個默認值,而不是覆蓋可能已經存在的值。 – Kevin 2010-09-27 21:44:20

+0

我認爲裝飾器是用於可調用的,覆蓋構造函數應該通過正常的繼承機制來完成。在Django中,有一些函數返回類並不罕見,這些函數通常被稱爲「工廠」。更新爲「if」條件(未經測試)。 – 2010-09-28 15:02:40

3

與CSS類創建一個新的widget

class ContactForm(forms.Form): 
    subject = TextField(widget=PrettyWidget) 
+2

這感覺更Djangonic的方式來完成任務,但它並不完全看起來像什麼凱文是我後... – codekoala 2010-09-24 14:43:19

4

一件事,我已經在過去做的是創造返回領域的lambda函數我經常使用:

from django import forms 

fancy = lambda: forms.TextInput(attrs={'class': 'derp'}) 

class MyForm(forms.Form): 
    attr1 = fancy() 
    attr2 = fancy() 
    attr3 = fancy() 

我不記得到底爲什麼我選擇使用一個函數T Ø處理我的情況,但我懷疑它有一些東西需要與創建forms.TextInput對象每個表單字段的不同實例....

+0

這是我現在要做的。有必要創建單獨的forms.Select實例。 – Kevin 2010-09-26 23:59:33

1

您可以使用下面:

def set_attrs_for_fields(fields, default_attrs): 
    for field_name in fields: 
     field = fields[field_name] 

     try: 
      default_widget_attr = default_attrs[field.widget.__class__] 
      field.widget.attrs = default_widget_attr 
     except KeyError: 
      pass 


class DefaultAttrForm(forms.Form): 

    def __init__(self, *args, **kwargs): 

     super(DefaultAttrForm, self).__init__(*args, **kwargs) 

     set_attrs_for_fields(self.fields, self.get_default_attrs()) 


    def get_default_attrs(self): 
     ''' 
     Child class should overwrite this method and return dict with example format 

     {forms.TextInput: {'class': 'my_value'}} 

     where keys, are widget classes for which default attrs will be set. 
     ''' 
     raise NotImplementedError() 


class DefaultAttrModelForm(ModelForm): 

    def __init__(self, *args, **kwargs): 

     super(DefaultAttrModelForm, self).__init__(*args, **kwargs) 

     set_attrs_for_fields(self.fields, self.get_default_attrs()) 


    def get_default_attrs(self): 
     ''' 
     Child class should overwrite this method and return dict with example format 

     {forms.TextInput: {'class': 'my_value'}} 

     where keys, are widget classes for which default attrs will be set. 
     ''' 
     raise NotImplementedError() 

現在,每次你想爲某個小部件使用默認attrs時,你只需要創建繼承自DefaultAttrForm或DefaultAttrModelForm的類並覆蓋方法get_default_attrs。例如,對於普通的Django形式:

class MyForm(DefaultAttrForm): 
    my_field1 = forms.CharField(widget=forms.TextInput()) 
    my_field2 = forms.CharField(widget=forms.PasswordInput(attrs={'my_non_default': 'Non default'})) 

    def get_default_attrs(self): 
     # all fields with widget TextInput will have 
     # default attrs set to {'class': 'my_value'} 

     return {forms.TextInput: {'class': 'my_value'}, 
       } 


In [1]: form = MyForm() 

In [2]: form.fields['my_field1'].widget.attrs 
Out[2]: {'class': 'my_value'} 

In [3]: form.fields['my_field2'].widget.attrs 
Out[3]: {'my_non_default': 'Non default'} 

對於型號形式使用下列內容:

class MyModelForm(DefaultAttrModelForm): 

    class Meta: 
     model = my_model 

    def get_default_attrs(self): 
     # all fields with widget TextInput will have 
     # default attrs set to {'class': 'my_value'} 

     return {forms.TextInput: {'class': 'my_value'}, 
       } 


In [1]: form = MyModelForm() 

In [2]: form.fields['my_field1'].widget.attrs 
Out[2]: {'class': 'my_value'} 

In [3]: form.fields['my_field2'].widget.attrs 
Out[3]: {'my_non_default': 'Non default'} 
0

對於ModelForm,我們可以使用它。

from django import forms 
from django.contrib.auth.models import User 

class UserForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(UserForm, self).__init__(*args, **kwargs) 

     # change a widget attribute: 
     self.fields['user_permissions'].widget.attrs["size"] = 5 
     self.fields['user_permissions'].widget.attrs["class"] = 'form-control required' 

    class Meta: 
     model = User