2010-09-09 5 views

Répondre

13

Vous pouvez remplacer le constructeur afin de modifier tous les widgets 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 

pouvez-vous override init avec un décorateur? aussi, il devrait y avoir une instruction if avant l'attrs.update() parce que je veux définir un défaut plutôt que de surcharger ce qui peut déjà être là. - Kevin

Non testé, mais je suppose que vous pouvez simplement hériter de MyForm si vous l'utilisez beaucoup.

+0

pouvez-vous remplacer init avec un décorateur? aussi, il devrait y avoir une instruction if avant l'attrs.update() parce que je veux définir un défaut plutôt que de surcharger ce qui peut déjà être là. – Kevin

+0

Je pense que les décorateurs sont destinés à être utilisés avec des callables, le remplacement du constructeur devrait être fait par le mécanisme d'héritage normal. Dans django, il n'est pas rare que certaines fonctions renvoient des classes, ces fonctions sont généralement appelées «usines». Mise à jour avec la condition "si" (non testée). –

3

Créer un nouveau widget avec votre classe CSS:

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

Dans votre formulaire Utilisez votre nouveau widget dans tous vos domaines:

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

Cela se sent comme le moyen le plus Djangonic pour accomplir la tâche, mais il ne semble pas tout à fait ce que Kevin est après moi ... – codekoala

4

Une chose que je l'ai fait dans le passé est de créer une fonction lambda qui renvoie les champs que j'utilise souvent:

from django import forms 

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

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

Je ne me souviens pas exactement pourquoi j'ai choisi d'utiliser une fonction t o gérer ma situation, mais je pense qu'il avait quelque chose à voir avec la création d'instances distinctes de l'objet forms.TextInput pour chaque champ de formulaire ....

+0

C'est ce que je fais maintenant. Il est nécessaire de créer des instances séparées de formulaires. Sélectionnez. – Kevin

1

Vous pouvez utiliser ce qui suit:

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

Maintenant, Chaque fois que vous voulez utiliser l'attr par défaut pour un widget, vous devez simplement créer une classe qui hérite de DefaultAttrForm ou DefaultAttrModelForm et remplacer la méthode get_default_attrs. Exemple pour la forme normale 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'} 

Pour une utilisation du formulaire modèle suivant:

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

Pour ModelForm nous pouvons l'utiliser.

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 
Questions connexes