Django-Admin: CharField как TextArea

Я

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 )

как назначить виджет TextArea полю "descr" в интерфейсе администратора?

upd:
В Admin только интерфейс!

хорошая идея использовать ModelForm.

9 ответов


вам придется создать forms.ModelForm это опишет, как вы хотите descr поле для отображения, а потом сказать admin.ModelAdmin использовать эту форму. Например:

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

на на admin.ModelAdmin описанное в официальной документации Django. Вот одно место, чтобы посмотреть на.


в этом случае лучший вариант, вероятно, просто использовать текстовое поле вместо CharField в вашей модели. Вы также можете переопределить formfield_for_dbfield метод 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

Ayaz имеет довольно много места, за исключением небольшого изменения(?!):

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)

Итак, вам не нужно переопределять поле в ModelForm, чтобы изменить его виджет, просто установите виджеты dict в Meta.


Вы можете подкласс своем поле с необходимой formfield способ:

class CharFieldWithTextarea(models.CharField):
    def formfield(self, **kwargs):
         kwargs.update(
            "widget": forms.Textarea
         )
         return super(CharFieldWithTextarea, self).formfield(**kwargs)

это повлияет на все сгенерированные формы.


Если вы пытаетесь изменить Textarea на admin.py, это решение, которое сработало для меня:

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)

Если вы используете MySQL DB, ваша длина столбца обычно будет автосет до 250 символов, поэтому вы захотите запустить ALTER TABLE, чтобы изменить длину в Вас MySQL DB, чтобы вы могли воспользоваться новым большим Textarea, который у вас есть на сайте администратора Django.


вместо models.CharField используйте models.TextField на descr.


хотел расширить ответ Карла Мейера, который отлично работает до этой даты.

Я всегда использую TextField вместо CharField (С или без выбора) и накладывают ограничения символов на стороне UI/API, а не на уровне БД. Чтобы сделать эту работу динамически:

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

у меня есть имя модели Post здесь title, slug & state are TextFields и state есть выбор. Определение администратора выглядит так:

@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']

думал, что другие ищут ответы могут оказаться полезными.


можно использовать models.TextField для этого:

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

вам не нужно создавать класс формы самостоятельно:

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)

посмотреть ModelAdmin.get_form.