2009-01-10 25 views
65

Tôi cóDjango-Admin: CharField như 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) 

làm thế nào để gán phụ tùng TextArea đến trường 'descr' trong giao diện quản trị?

UPD:
Trong quản lý giao diện duy nhất!

Ý tưởng tốt để sử dụng ModelForm.

+1

Câu trả lời được chấp nhận là quá mức cần thiết cho mục đích modficiation chỉ là một trường! NHÂN DÂN THEO D THI này ĐÁP ỨNG bởi Carl Meyer CHO MỤC ĐÍCH ĐƠN GIẢN: http://stackoverflow.com/questions/430592/django-admin-charfield-as-textarea#431412 – andi

Trả lời

78

Bạn sẽ phải tạo một forms.ModelForm sẽ mô tả cách bạn muốn trường descr được hiển thị và sau đó yêu cầu admin.ModelAdmin sử dụng biểu mẫu đó. Ví dụ:

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 

Các form thuộc tính của admin.ModelAdmin được ghi chép lại trong các tài liệu chính thức Django. Đây là one place to look at.

+3

Chỉ cần thay thế một tiện ích biểu mẫu, bạn không phải tạo toàn bộ biểu mẫu của riêng mình. Bạn chỉ có thể ghi đè 'formfield_for_dbfield' trên' ModelAdmin' của bạn, xem câu trả lời của tôi bên dưới. –

+1

Điều này cung cấp cho 'django.core.exceptions.ImproperlyConfigured: Tạo một ModelForm mà không có thuộc tính 'fields' hoặc thuộc tính 'exclude' bị cấm ' –

+3

Bắt đầu từ Django 1.7, bạn cũng cần thêm' fields =' __all __ ''trong' lớp Meta: '. – skoll

2

Thay vì models.CharField, hãy sử dụng models.TextField cho descr.

+4

Thật không may, max_length = hoàn toàn bị bỏ qua bởi Django trên một TextField, vì vậy khi bạn cần xác nhận độ dài trường (chẳng hạn như cho phép các thư ký nhập tóm tắt sự kiện), cách duy nhất để có được nó là sử dụng CharField. Nhưng một CharField là cách để ngắn để gõ 300 ký tự vào. Do đó giải pháp ayaz. – shacker

+0

Tuyệt đối! Cảm ơn. –

+2

Đây không phải là câu trả lời hay vì nó thay đổi cơ sở dữ liệu. Điểm thay đổi tiện ích là thay đổi cách hiển thị trường, không thay đổi lược đồ cơ sở dữ liệu –

12

Bạn có thể phân lớp lĩnh vực của riêng bạn với cần formfield phương pháp:

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

này sẽ có hiệu lực trên tất cả các hình thức tạo ra.

45

Đối với trường hợp này, tùy chọn tốt nhất có lẽ chỉ là sử dụng TextField thay vì CharField trong mô hình của bạn. Bạn cũng có thể ghi đè lên các phương pháp formfield_for_dbfield của lớp ModelAdmin của bạn:

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

có nhược điểm nào trong số này so với câu trả lời đã chọn không? này trông sạch hơn để thực hiện như chúng ta không cần phải tạo ra một ModelForm mới ... –

+1

thay thế 'formfield.widget = forms.Textarea()' với 'formfield.widget = forms.Textarea (attrs = formfield.widget.attrs) 'để giữ tất cả các thuộc tính được tạo tự động cho TextField, Cảm ơn! –

+1

Tôi không biết tại sao câu trả lời khác được chấp nhận trong câu trả lời này; Tôi nghĩ nếu tất cả những gì bạn đang làm là thay thế một widget thì điều này đơn giản hơn. Nhưng một trong hai sẽ làm việc tốt. –

29

Ayaz có khá nhiều chỗ trên, ngoại trừ một thay đổi nhỏ (?!):

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) 

Vì vậy, bạn không cần để xác định lại một trường trong ModelForm để thay đổi widget của nó, chỉ cần đặt dict widget trong Meta.

+1

Điều này giữ lại các thuộc tính "tự động" hơn câu trả lời của Ayaz, nhưng bất kỳ mẹo nào về cách giữ cho xác nhận độ dài trường là tốt? –

5

Nếu bạn đang cố gắng để thay đổi Textarea trên admin.py, đây là giải pháp mà làm việc cho tôi:

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) 

Nếu bạn đang sử dụng một DB MySQL, chiều dài cột của bạn thường sẽ được autoset đến 250 các ký tự, vì vậy bạn sẽ muốn chạy ALTER TABLE để thay đổi độ dài trong MySQL DB của bạn, để bạn có thể tận dụng lợi thế của Textarea lớn hơn mà bạn có trong trang Admin Django của bạn.

0

Muốn mở rộng câu trả lời của Carl Meyer, hoạt động hoàn hảo cho đến ngày này.

Tôi luôn sử dụng TextField thay vì CharField (có hoặc không có lựa chọn) và áp đặt giới hạn ký tự trên giao diện người dùng/API thay vì ở cấp DB. Để làm việc này tự động:

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 

Tôi có một tên mô hình Post nơi title, slug & stateTextField s và state có sự lựa chọn.Định nghĩa quản trị trông giống như:

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

Những người khác tìm kiếm câu trả lời có thể thấy điều này hữu ích.