web-dev-qa-db-fra.com

Django-Admin: CharField comme TextArea

J'ai

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?

pd:
Dans l'interface Admin uniquement!

Bonne idée d'utiliser ModelForm.

76
maxp

Vous devrez créer un forms.ModelForm qui décrira comment vous voulez que le champ descr soit affiché, puis indiquera 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

L'attribut form de admin.ModelAdmin est documenté dans la documentation officielle Django. Voici n endroit à consulter .

88
ayaz

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

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
52
Carl Meyer

Ayaz a à peu près sa place, à 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 ModelForm pour changer son widget, il suffit de définir le dict des widgets dans Meta.

31
Gezim

Vous pouvez sous-classer votre propre champ avec la méthode formfield nécessaire:

class CharFieldWithTextarea(models.CharField):

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

Cela prendra effet sur tous les formulaires générés.

13
Alex Koshelev

Vous n'avez pas besoin de créer la classe de formulaire vous-même:

from Django.contrib import admin
from Django import forms

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        kwargs['widgets'] = {'descr': forms.Textarea}
        return super().get_form(request, obj, **kwargs)

admin.site.register(MyModel, MyModelAdmin)

Voir ModelAdmin.get_form .

7
x-yuri

Si vous essayez de modifier la zone de texte sur admin.py, voici la solution qui a fonctionné pour moi:

from Django import forms
from Django.contrib import admin
from Django.db import models
from Django.forms import TextInput, Textarea

from books.models import Book

class BookForm(forms.ModelForm):
    description = forms.CharField( widget=forms.Textarea(attrs={'rows': 5, 'cols': 100}))
    class Meta:
        model = Book

class BookAdmin(admin.ModelAdmin):
    form = BookForm

admin.site.register(Book, BookAdmin)

Si vous utilisez une base de données MySQL, la longueur de votre colonne sera généralement définie automatiquement sur 250 caractères, vous voudrez donc exécuter une ALTER TABLE pour modifier la longueur de votre base de données MySQL, afin que vous puissiez profiter de la nouvelle zone de texte plus grande que vous avez en vous Admin Django site.

5
Aaron Lelevier

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

3
mipadi

Je voulais développer la réponse de Carl Meyer, qui fonctionne parfaitement jusqu'à cette date.

J'utilise toujours TextField au lieu de CharField (avec ou sans choix) et j'impose des limites de caractères côté UI/API plutôt qu'au niveau DB. Pour que cela fonctionne dynamiquement:

from Django import forms
from Django.contrib import admin


class BaseAdmin(admin.ModelAdmin):
    """
    Base admin capable of forcing widget conversion
    """
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(BaseAdmin, self).formfield_for_dbfield(
            db_field, **kwargs)

        display_as_charfield = getattr(self, 'display_as_charfield', [])
        display_as_choicefield = getattr(self, 'display_as_choicefield', [])

        if db_field.name in display_as_charfield:
            formfield.widget = forms.TextInput(attrs=formfield.widget.attrs)
        Elif db_field.name in display_as_choicefield:
            formfield.widget = forms.Select(choices=formfield.choices,
                                            attrs=formfield.widget.attrs)

        return formfield

J'ai un nom de modèle Posttitle, slug & state sont TextFields et state a des choix. La définition d'administrateur ressemble à ceci:

@admin.register(Post)
class PostAdmin(BaseAdmin):
    list_display = ('pk', 'title', 'author', 'org', 'state', 'created',)
    search_fields = [
        'title',
        'author__username',
    ]
    display_as_charfield = ['title', 'slug']
    display_as_choicefield = ['state']

Je pensais que d'autres cherchant des réponses pourraient trouver cela utile.

3
tarequeh

Vous pouvez utiliser models.TextField dans ce but:

class Sample(models.Model):
    field1 = models.CharField(max_length=128)
    field2 = models.TextField(max_length=1024*2)   # Will be rendered as textarea
3
vk-code