Django-Admin: TextArea olarak CharField


88

Sahibim

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 widget'ı yönetici arayüzündeki 'descr' alanına nasıl atanır?

gnc:
In Yönetici arayüzü yalnızca!

ModelForm'u kullanmak iyi bir fikir.


3
Kabul edilen cevap, sadece bir alanda modifikasyon amacıyla büyük bir aşırılıktır! İNSANLAR BU
CEVABI KOLAYLIK

Yanıtlar:


99

Alanın forms.ModelFormnasıl descrgörüntülenmesini istediğinizi açıklayan bir tane oluşturmanız ve ardından admin.ModelAdminbu formu kullanmayı söylemeniz gerekecektir. Örneğin:

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Öznitelik admin.ModelAdminresmi Django belgelerinde belgelenmiştir. Bakılacak bir yer burası .


6
Bir form widget'ını basitçe değiştirmek için, kendi formunuzun tamamını oluşturmanız gerekmez. Sadece formfield_for_dbfieldsenin üzerine yazabilirsin ModelAdmin, aşağıdaki cevabıma bakın.
Carl Meyer

1
Bu verirdjango.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited
John Wu

4
Django 1.7'den başlayarak fields = '__all__'altına da eklemeniz gerekir class Meta:.
2016 saat

2
Formu kendiniz oluşturmanız gerekmez, get_formyöntemi geçersiz kılabilirsiniz . Cevabımı gör .
x-yuri

beeter yaklaşımı, Meta sınıfı Meta: model = Mesaj widget'ları = {'text': forms.Textarea (attrs = {'cols': 80, 'rows': 20}),}
Amulya Acharya

58

Bu durumda, en iyi seçenek muhtemelen modelinizde CharField yerine bir TextField kullanmaktır. Ayrıca sınıfınızın formfield_for_dbfieldyöntemini de geçersiz kılabilirsiniz 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

Bunda seçilen cevaba göre herhangi bir dezavantaj var mı? yeni bir ModelForm oluşturmamıza gerek olmadığından bu uygulama daha temiz görünüyor ...
Filipe Pina

3
TextField için otomatik olarak oluşturulan tüm öznitelikleri korumak için formfield.widget = forms.Textarea()ile değiştirilir formfield.widget = forms.Textarea(attrs=formfield.widget.attrs), Teşekkürler!
Filipe Pina

2
Bunun üzerine diğer cevabın neden kabul edildiğini bilmiyorum; Bence tek yaptığınız bir widget'ı değiştirmekse bu daha basit. Ama her ikisi de iyi çalışacak.
Carl Meyer

Bu mükemmel çalıştı, teşekkürler. Super () invocation biraz ayrıntılı görünse de, bunu yapmanın daha basit bir yolu var mı?
RJH

2
@rjh py3'te parens içindeki her şeyi kaldırabilir ve sadece kullanabilirsiniz super(). Aksi takdirde hayır.
Carl Meyer

33

Ayaz, küçük bir değişiklik dışında (?!)

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)

Bu nedenle, ModelForm'daki bir alanı, widget'ını değiştirmek için yeniden tanımlamanıza gerek yoktur, sadece Meta'da widget diktesini ayarlayın.


1
Bu, Ayaz'ın cevabından daha "otomatik" özellikleri koruyor, ancak alan uzunluğu doğrulamasını nasıl koruyacağınıza dair herhangi bir ipucu var mı?
Filipe Pina

14

Kendi alanınızı gerekli formfieldyöntemle alt sınıflara ayırabilirsiniz :

class CharFieldWithTextarea(models.CharField):

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

Bu, oluşturulan tüm formları etkileyecektir.


9

Form sınıfını kendiniz oluşturmanız gerekmez:

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'a bakın .


7

A yerine, for models.CharFieldkullanın .models.TextFielddescr


4
Ne yazık ki, max_length = bir TextField üzerinde Django tarafından tamamen yok sayılır, bu yüzden alan uzunluğu doğrulamasına ihtiyaç duyduğunuzda (sekreterlerin olay özetleri girmesine izin vermek gibi) bunu elde etmenin tek yolu bir CharField kullanmaktır. Ancak bir CharField, 300 karakter yazmanın kısaltmasıdır. Ayaz çözümü buradan gelir.
shacker

3
Bu iyi bir cevap değil çünkü veritabanını değiştiriyor. Widget'ı değiştirmenin amacı, veritabanı şemasını değiştirmek değil, alanın görüntülenme şeklini değiştirmektir

1
Django'yu nasıl kullanacağını öğrenen ve daha iyi bilseydim veritabanını ilk etapta farklı bir şekilde kuracak olan (benim gibi) biri için harika bir cevap.
Andrew Swift

7

Admin.py adresindeki Metin alanını değiştirmeye çalışıyorsanız, benim için çalışan çözüm şudur:

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)

Bir MySQL DB kullanıyorsanız, sütun uzunluğunuz genellikle 250 karaktere otomatik olarak ayarlanacaktır, bu nedenle MySQL DB'nizdeki uzunluğu değiştirmek için bir ALTER TABLE çalıştırmak isteyeceksiniz, böylece yeni daha büyük Textarea'dan yararlanabilirsiniz. Yönetici Django sitenizde var.


5

models.TextFieldBu amaçla kullanabilirsiniz :

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

3
Bu DB yapısını değiştirecek, bu yüzden dikkatli olun
elad silver

3

Bu tarihe kadar mükemmel çalışan Carl Meyer'in cevabını genişletmek istedi.

Her zaman TextFieldyerine CharField(seçimli veya seçimli) kullanıyorum ve DB seviyesi yerine UI / API tarafında karakter sınırlamaları koyuyorum. Bunun dinamik olarak çalışmasını sağlamak için:

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

Ben manken adı var Postnerede title, slug& stateolan TextFields ve stateseçeneği vardır. Yönetici tanımı şöyle görünür:

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

Cevap arayanların bunu yararlı bulabileceğini düşündüm.


Bu formfield_for_dbfieldbelgelenmiş mi?
x-yuri
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.