2009-01-10 75 views
65

tengoDjango-Admin: CharField como 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) 

cómo asignar widget de TextArea al campo 'descr' en la interfaz de administración?

UPD:
En Sólo administrador interfaz!

Buena idea de usar ModelForm.

+1

¡La respuesta aceptada es una gran exageración con el único propósito de modificar un campo! LAS PERSONAS SIGUEN ESTA RESPUESTA POR Carl Meyer PARA EL PROPÓSITO DE LA SIMPLICIDAD: http://stackoverflow.com/questions/430592/django-admin-charfield-as-textarea#431412 – andi

Respuesta

78

Usted tendrá que crear un forms.ModelForm que describa cómo desea que el campo descr que se mostrará, y luego decirle admin.ModelAdmin utilizar esa forma. Por ejemplo:

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 atributo form de admin.ModelAdmin se documenta en la documentación oficial de Django. Aquí está one place to look at.

+3

Para simplemente reemplazar un widget de formulario, no tiene que crear su propio formulario completo. Puede simplemente anular 'formfield_for_dbfield' en su' ModelAdmin', vea mi respuesta a continuación. –

+1

Esto da 'django.core.exceptions.ImproperlyConfigured: Crear un ModelForm sin el atributo 'fields' o el atributo 'exclude' está prohibido' –

+3

Comenzando desde Django 1.7 necesita agregar también' fields = '__all __' 'under' clase Meta: '. – skoll

2

En lugar de models.CharField, utilice models.TextField para descr.

+4

Desafortunadamente, Django ignora por completo a max_length = en un TextField, por lo que cuando necesita la validación de la longitud de campo (como dejar que las secretarias ingresen resúmenes de eventos), la única manera de obtenerlo es usar un CharField. Pero un CharField es demasiado corto para escribir 300 caracteres. De ahí la solución de Ayaz. – shacker

+0

¡Absolutamente! Gracias. –

+2

Esta no es una buena respuesta porque cambia la base de datos. El punto de cambiar el widget es cambiar la forma en que se muestra el campo, no cambiar el esquema de la base de datos –

12

Usted puede subclase su propio campo con formfield necesaria método:

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

Esto se llevará a efecto en todas las formas generadas.

45

En este caso, la mejor opción es, probablemente, solo utilizar TextField en lugar de CharField en su modelo. También puede reemplazar el método formfield_for_dbfield de la clase 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 
+0

¿hay algún inconveniente en esto en comparación con la respuesta seleccionada? esto parece más limpio para implementar ya que no necesitamos crear un nuevo ModelForm ... –

+1

reemplazado 'formfield.widget = forms.Textarea()' con 'formfield.widget = forms.Textarea (attrs = formfield.widget.attrs) 'para mantener todos los atributos generados automáticamente para el TextField, ¡Gracias! –

+1

No sé por qué se acepta la otra respuesta en este caso; Creo que si todo lo que estás haciendo es reemplazar un widget, es más simple. Pero cualquiera funcionará bien. –

29

Ayaz tiene más o menos acertadas, a excepción de un ligero cambio (?!):

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) 

Por lo tanto, no es necesario para redefinir un campo en el ModelForm para cambiar su widget, simplemente configure el wictts dict en Meta.

+1

Esto retiene más propiedades "automáticas" que la respuesta de Ayaz, pero ¿hay algún consejo sobre cómo mantener la validación de la longitud del campo también? –

5

Si usted está tratando de cambiar la caja de texto en admin.py, esta es la solución que funcionó para mí:

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 está utilizando una base de datos MySQL, la longitud de la columna por lo general se autoSET a 250 caracteres, por lo que querrá ejecutar una ALTER TABLE para cambiar la longitud en su MySQL DB, para que pueda aprovechar el nuevo Textarea más grande que tiene en su sitio Admin Django.

0

Quería ampliar la respuesta de Carl Meyer, que funciona perfectamente hasta esta fecha.

Siempre uso TextField en lugar de CharField (con o sin opciones) e impongo límites de caracteres en el lado de UI/API en lugar de a nivel de base de datos. Para hacer este trabajo de forma dinámica:

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 

tengo un nombre de modelo, donde Posttitle, slug & state son TextField s state y tiene opciones.La definición de administrador se ve así:

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

Pensamos que a los demás que busquen respuestas les puede resultar útil.