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:
Только в интерфейсе Админ!

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

Принятый ответ - это огромный перебор с целью модификации только одного поля! ЛЮДИ ПОСЛЕДУЮТ ЭТОМ ОТВЕТУ Карла Мейера ДЛЯ ПРОСТОТЫ: stackoverflow.com/questions/430592/…

andilabs 30.10.2014 13:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
92
1
80 449
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Вместо models.CharField используйте models.TextField для descr.

К сожалению, max_length = полностью игнорируется Django в TextField, поэтому, когда вам нужна проверка длины поля (например, разрешение секретарям вводить сводки событий), единственный способ получить это - использовать CharField. Но CharField - это способ сократить до 300 символов. Отсюда и решение аяз.

shacker 22.04.2009 03:45

Это плохой ответ, потому что он меняет базу данных. Смысл изменения виджета - изменить способ отображения поля, а не схему базы данных.

user9903 15.02.2013 01:11

Это отличный ответ для кого-то (вроде меня), который учится использовать Django и, если бы я знал лучше, изначально настроил бы базу данных по-другому.

Andrew Swift 15.01.2017 16:17
Ответ принят как подходящий

Вам нужно будет создать 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

Атрибут form для admin.ModelAdmin задокументирован в официальной документации Django. Вот одно место, на которое можно посмотреть.

Для простой замены виджета формы вам не нужно создавать свою собственную форму целиком. Вы можете просто переопределить formfield_for_dbfield на вашем ModelAdmin, см. Мой ответ ниже.

Carl Meyer 03.12.2013 00:25

Это дает django.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited

John Wu 23.02.2016 18:55

Начиная с Django 1.7 вам необходимо добавить также fields = '__all__' под class Meta:.

skoll 04.05.2016 14:43

Вам не нужно создавать форму самостоятельно, вы можете переопределить метод get_form. См. мой ответ.

x-yuri 25.05.2018 07:29

Подход beeter заключается в использовании мета-класса Meta: model = Message widgets = {'text': forms.Textarea (attrs = {'cols': 80, 'rows': 20}),}

Amulya Acharya 25.03.2019 07:20

Вы можете создать подкласс своего собственного поля с помощью необходимого метода formfield:

class CharFieldWithTextarea(models.CharField):

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

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

В этом случае лучшим вариантом, вероятно, будет просто использовать TextField вместо 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

есть ли в этом обратная сторона по сравнению с выбранным ответом? это выглядит более понятным для реализации, поскольку нам не нужно создавать новую ModelForm ...

Filipe Pina 23.02.2012 14:30

заменил formfield.widget = forms.Textarea() на formfield.widget = forms.Textarea(attrs=formfield.widget.attrs), чтобы сохранить все атрибуты, автоматически сгенерированные для TextField, спасибо!

Filipe Pina 23.02.2012 14:53

Я не знаю, почему принимается другой ответ вместо этого; Я думаю, что если все, что вы делаете, это заменяете виджет, это проще. Но и то, и другое будет работать нормально.

Carl Meyer 23.02.2012 19:20

Это сработало отлично, спасибо. Вызов super () кажется немного многословным, есть ли более простой способ сделать это?

rjh 25.04.2015 10:08

@rjh В py3 вы можете исключить все, что находится внутри скобок, и просто использовать super(). В противном случае нет.

Carl Meyer 25.04.2015 17:27

@CarlMeyer: есть ли способ сохранить все атрибуты Charfield в текстовом поле, а также новые атрибуты, такие как столбцы и строки.

Anurag Rana 17.01.2017 20:15

Вы также должны добавить: admin.site.register(Cab, CabAdmin) после определения класса

nbeuchat 22.06.2017 05:51

Документирован ли formfield_for_dbfield?

x-yuri 25.05.2018 07:21

Использование TextField вместо CharField в модели является изменением на уровне базы данных и может иметь непредвиденные последствия. Есть причина, по которой это отдельные поля. Правильный способ сделать это - переопределить виджет.

Adam Barnes 02.10.2018 09:26

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

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.

Это сохраняет больше "автоматических" свойств, чем ответ Аяза, но есть ли подсказки о том, как сохранить проверку длины поля?

Filipe Pina 23.02.2012 14:44

Если вы пытаетесь изменить 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, длина вашего столбца обычно будет автоматически установлена ​​на 250 символов, поэтому вам нужно будет запустить ALTER TABLE, чтобы изменить длину в вашей базе данных MySQL, чтобы вы могли воспользоваться преимуществами нового большего Textarea, которое вы есть у вас админский сайт Django.

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

Я всегда использую 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 - это TextField, а у 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']

Подумал, что другие, ищущие ответы, могут найти это полезным.

Документирован ли этот formfield_for_dbfield?

x-yuri 25.05.2018 07:18

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

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

Это изменит структуру БД, поэтому будьте осторожны.

elad silver 05.12.2018 21:04

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

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.

Другие вопросы по теме