97 votes

Django-Admin : CharField comme TextArea

Tengo

class Cab(models.Model):
    name  = models.CharField( max_length=20 )
    descr = models.CharField( max_length=2000 )

class Cab_Admin(admin.ModelAdmin):
    ordering     = ('name',)
    list_display = ('name','descr', )
    # what to write here to make descr using TextArea?

admin.site.register( Cab, Cab_Admin )

comment attribuer le widget TextArea au champ 'descr' dans l'interface d'administration ?

upd :
Sur Admin interface uniquement !

Bonne idée d'utiliser ModelForm.

103voto

ayaz Points 6910

Vous devrez créer un forms.ModelForm qui décrira comment vous voulez que le descr à afficher, puis dites admin.ModelAdmin pour utiliser ce formulaire. Par exemple :

from django import forms
class CabModelForm( forms.ModelForm ):
    descr = forms.CharField( widget=forms.Textarea )
    class Meta:
        model = Cab

class Cab_Admin( admin.ModelAdmin ):
    form = CabModelForm

El form l'attribut de admin.ModelAdmin est documenté dans la documentation officielle de Django. Voici un endroit à regarder .

6 votes

Pour remplacer simplement un widget de formulaire, vous n'avez pas besoin de créer votre propre formulaire complet. Vous pouvez simplement remplacer formfield_for_dbfield sur votre ModelAdmin voir ma réponse ci-dessous.

1 votes

Cela donne django.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited

4 votes

À partir de Django 1.7, vous devez ajouter aussi fields = '__all__' sous class Meta: .

64voto

Carl Meyer Points 30736

Dans ce cas, la meilleure option est probablement d'utiliser un TextField au lieu d'un CharField dans votre modèle. Vous pouvez également remplacer la méthode formfield_for_dbfield de votre ModelAdmin classe :

class CabAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(CabAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'descr':
            formfield.widget = forms.Textarea(attrs=formfield.widget.attrs)
        return formfield

0 votes

Y a-t-il un inconvénient à cette solution par rapport à la réponse choisie ? Elle semble plus simple à mettre en œuvre car nous n'avons pas besoin de créer un nouveau ModelForm...

3 votes

A remplacé formfield.widget = forms.Textarea() con formfield.widget = forms.Textarea(attrs=formfield.widget.attrs) pour garder tous les attributs générés automatiquement pour le TextField, Merci !

2 votes

Je ne sais pas pourquoi l'autre réponse est préférée à celle-ci ; je pense que si tout ce que vous faites est de remplacer un widget, celle-ci est plus simple. Mais l'une ou l'autre fonctionnera très bien.

35voto

Gezim Points 1559

Ayaz a pratiquement tout compris, à l'exception d'un léger changement ( ?!):

class MessageAdminForm(forms.ModelForm):
    class Meta:
        model = Message
        widgets = {
            'text': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
        }

class MessageAdmin(admin.ModelAdmin):
    form = MessageAdminForm
admin.site.register(Message, MessageAdmin)

Ainsi, vous n'avez pas besoin de redéfinir un champ dans le ModelForm pour changer son widget, il suffit de définir le dict des widgets dans Meta.

1 votes

Cela conserve plus de propriétés "automatiques" que la réponse d'Ayaz, mais un conseil sur la façon de conserver la validation de la longueur du champ également ?

14voto

Alex Koshelev Points 5522

Vous pouvez sous-classer votre propre champ avec les données nécessaires. formfield méthode :

class CharFieldWithTextarea(models.CharField):

    def formfield(self, **kwargs):
        kwargs.update({"widget": forms.Textarea})
        return super(CharFieldWithTextarea, self).formfield(**kwargs)

Cette mesure s'appliquera à tous les formulaires générés.

5voto

mipadi Points 135410

Au lieu d'un models.CharField utiliser un models.TextField pour descr .

4 votes

Malheureusement, max_length= est totalement ignoré par Django sur un TextField, donc lorsque vous avez besoin d'une validation de la longueur du champ (comme pour permettre aux secrétaires de saisir les résumés des événements), la seule façon de l'obtenir est d'utiliser un CharField. Mais un CharField est bien trop court pour qu'on puisse y taper 300 caractères. D'où la solution ayaz.

3 votes

Ce n'est pas une bonne réponse car cela modifie la base de données. Le but de la modification du widget est de changer la façon dont le champ est affiché, et non de modifier le schéma de la base de données.

1 votes

C'est une excellente réponse pour quelqu'un (comme moi) qui apprend à utiliser Django et qui aurait configuré la base de données différemment si j'avais été mieux informé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X