2010-08-12 34 views
22

Tôi có trường biểu mẫu Tùy chỉnh TagField.Quản trị Django - Ghi đè tiện ích của trường biểu mẫu tùy chỉnh

class TagField(forms.CharField): 
    def __init__(self, *args, **kwargs): 
     super(TagField, self).__init__(*args, **kwargs) 
     self.widget = forms.TextInput(attrs={'class':'tag_field'}) 

Như đã thấy ở trên, nó sử dụng tiện ích trường biểu mẫu TextInput. Nhưng trong admin tôi muốn nó được hiển thị bằng cách sử dụng widget Textarea. Đối với điều này, có formfield_overrides móc nhưng nó không hoạt động cho trường hợp này.

Việc kê khai quản trị là:

class ProductAdmin(admin.ModelAdmin): 
    ... 
    formfield_overrides = { 
     TagField: {'widget': admin.widgets.AdminTextareaWidget}, 
    } 

này không ảnh hưởng đến các widget trường biểu mẫu và tags vẫn được trả lại với một widget TextInput.

Bất kỳ trợ giúp nào được đánh giá cao.

-
omat

Trả lời

40

Quản trị viên django sử dụng các tiện ích tùy chỉnh cho nhiều trường của nó. Cách ghi đè trường là tạo Biểu mẫu để sử dụng với đối tượng ModelAdmin.

# forms.py 

from django import forms 
from django.contrib import admin 

class ProductAdminForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(ProductAdminForm, self).__init__(*args, **kwargs) 
     self.fields['tags'].widget = admin.widgets.AdminTextareaWidget() 

Sau đó, trong đối tượng ModelAdmin của bạn, bạn chỉ định dạng:

from django.contrib import admin 
from models import Product 
from forms import ProductAdminForm 

class ProductAdmin(admin.ModelAdmin): 
    form = ProductAdminForm 

admin.site.register(Product, ProductAdmin) 

Bạn cũng có thể ghi đè lên các queryset vào thời điểm này: để lọc đối tượng theo một lĩnh vực trong mô hình, ví dụ (kể từ limit_choices_to không thể xử lý này)

+0

Điều này không hiệu quả đối với tôi, bạn cần phải chuyển một thể hiện của tiện ích, chứ không phải là lớp học. Ví dụ, trường hợp này hoạt động hoàn hảo. –

+0

Tôi thường sẽ tạo biểu mẫu quản trị tùy chỉnh trong admin.py và không kết hợp chúng với forms.py. Điều này làm giảm sự trộn lẫn cho các nhà phát triển khác và giữ tất cả các mục quản trị cụ thể trong cùng một tệp .py. – MaestroFJP

+0

Điểm tốt @MaestroFJP. Tôi đã làm điều đó trong mã mới hơn của mình. Hoặc, có một mô hình con/admin.py, nếu bạn có các hình thức thực sự phức tạp, và rất nhiều trong số chúng. –

1

Cố gắng thay đổi lĩnh vực của bạn như thế này:

class TagField(forms.CharField): 
    def __init__(self, *args, **kwargs): 
     self.widget = forms.TextInput(attrs={'class':'tag_field'}) 
     super(TagField, self).__init__(*args, **kwargs) 

này sẽ cho phép sử dụng các widget mà xuất phát từ **kwargs. Nếu không, trường của bạn sẽ luôn sử dụng tiện ích form.TextInput.

+0

tôi đã áp dụng thay đổi nhưng bây giờ tất cả các trường thẻ được hiển thị dưới dạng Textarea. – omat

+0

Nhìn vào django.forms.fields Tôi thấy rằng cách chính xác để xác định các widget mặc định cho một lĩnh vực là: lớp TagField (form.CharField): widget = forms.TextInput def widget_attrs (self, widget): return {'class': 'tag_field'} Bạn không ghi đè phương thức '__init__'. Thử cái này. –

+0

cảm ơn nhưng vẫn không có may mắn. tất cả các trường thẻ được hiển thị dưới dạng Textarea, trên toàn bộ quản trị viên, không chỉ cho ProductAdmin. – omat

27

Bạn có thể ghi đè lên các vật dụng bằng cách mở rộng lĩnh vực lớp ModelForm Meta từ Django 1.2:

class ProductAdminForm(forms.ModelForm): 
    class Meta: 
     model = Product 
     widgets = { 
      'tags': admin.widgets.AdminTextareaWidget 
     } 

class ProductAdmin(admin.ModelAdmin): 
    form = ProductAdminForm 

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-fields

+3

Bắt đầu với Django 1.8, bạn nên thêm 'fields = '__all __'' vào 'Meta'. Vide http://stackoverflow.com/a/28306347/1161025. – maciek

Các vấn đề liên quan