Thay đổi kích thước các trường trong Django Admin


107

Django có xu hướng lấp đầy không gian theo chiều ngang khi thêm hoặc chỉnh sửa các mục nhập trên quản trị viên, nhưng trong một số trường hợp, thực sự lãng phí không gian, tức là khi chỉnh sửa trường ngày, rộng 8 ký tự hoặc CharField, cũng là 6 hoặc 8 rộng, và sau đó hộp chỉnh sửa có tối đa 15 hoặc 20 ký tự.

Làm cách nào để cho quản trị viên biết độ rộng của hộp văn bản hoặc chiều cao của hộp soạn thảo TextField?


9
Rõ ràng là bạn đã quên làm điều đó trong trường hợp này. Hơn hai năm sau. =)
casperOne

Dự án bị bỏ rơi và tôi đã không thấy mã trong một thời gian. Tôi có thể bắt đầu một dự án mới vào tháng tới, vì vậy có lẽ tôi sẽ tiếp tục điều này: D
Andor

Câu trả lời:


209

Bạn nên sử dụng ModelAdmin.formfield_overrides .

Nó khá dễ dàng - trong admin.py, xác định:

from django.forms import TextInput, Textarea
from django.db import models

class YourModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.CharField: {'widget': TextInput(attrs={'size':'20'})},
        models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':40})},
    }

admin.site.register(YourModel, YourModelAdmin)

1
Đây chính xác là những gì tôi đang tìm kiếm mà không cần phải thực hiện một số tùy chỉnh mẫu vô lý. Cảm ơn!
Chris

2
Lưu ý rằng điều này sẽ không hoạt động nếu filter_horizontalhoặc filter_verticalđược đặt cho các trường tương ứng trong YourModelAdmin. Tôi đã dành một ít thời gian để tìm ra điều này.
Dennis Golomazov

Có bất kỳ điều gì đáng sợ với điều này trong một hình thức? Tôi không tìm thấy cách đặt thuộc tính attrs cho tất cả các Textareas.
Julian

1
Tôi chỉ sử dụng models.TextField: {'widget': Textarea(attrs={'rows':4})}nhưng chiều rộng cũng trở nên nhỏ hơn.
Smit Johnth

Thật khó để có chúng có cùng kích thước rõ ràng.
Sören

44

Bạn có thể đặt các thuộc tính HTML tùy ý trên một tiện ích con bằng thuộc tính "attrs" của nó .

Bạn có thể thực hiện việc này trong quản trị viên Django bằng formfield_for_dbfield:

class MyModelAdmin(admin.ModelAdmin):
  def formfield_for_dbfield(self, db_field, **kwargs):
    field = super(ContentAdmin, self).formfield_for_dbfield(db_field, **kwargs)
    if db_field.name == 'somefield':
      field.widget.attrs['class'] = 'someclass ' + field.widget.attrs.get('class', '')
    return field

hoặc với lớp con Widget tùy chỉnh và từ điển formfield_overrides :

class DifferentlySizedTextarea(forms.Textarea):
  def __init__(self, *args, **kwargs):
    attrs = kwargs.setdefault('attrs', {})
    attrs.setdefault('cols', 80)
    attrs.setdefault('rows', 5)
    super(DifferentlySizedTextarea, self).__init__(*args, **kwargs)

class MyModelAdmin(admin.ModelAdmin):
  formfield_overrides = { models.TextField: {'widget': DifferentlySizedTextarea}}

29

Để thay đổi chiều rộng cho một trường cụ thể.

Thực hiện qua ModelAdmin.get_form :

class YourModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(YourModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['myfield'].widget.attrs['style'] = 'width: 45em;'
        return form

Theo tôi đây là câu trả lời tốt nhất, vì nó cho phép thay đổi các trường riêng lẻ mà không cần phải tạo một biểu mẫu mới.
rbennell

20

Một tùy chọn nhanh chóng và dễ dàng là chỉ cần cung cấp một mẫu tùy chỉnh cho mô hình được đề cập.

Nếu bạn tạo một mẫu có tên admin/<app label>/<class name>/change_form.htmlthì quản trị viên sẽ sử dụng mẫu đó thay vì mặc định. Nghĩa là, nếu bạn có một mô hình được đặt tên Persontrong một ứng dụng được đặt tên people, bạn sẽ tạo một mẫu có tên admin/people/person/change_form.html.

Tất cả các mẫu quản trị đều có một extraheadkhối mà bạn có thể ghi đè để đặt nội dung vào <head>và phần cuối cùng của câu đố là thực tế là mọi trường đều có id HTML id_<field-name>.

Vì vậy, bạn có thể đặt một cái gì đó như sau vào mẫu của mình:

{% extends "admin/change_form.html" %}

{% block extrahead %}
  {{ block.super }}
  <style type="text/css">
    #id_my_field { width: 100px; }
  </style>
{% endblock %}

Cảm ơn! Câu trả lời này và câu trả lời của alanjds rất hữu ích cho việc thay đổi bố cục trong giao diện quản trị trên cơ sở từng trường, thay vì cơ sở từng loại trường.
nealmcb

10

Nếu bạn muốn thay đổi các thuộc tính trên một phiên bản cho mỗi trường, bạn có thể thêm thuộc tính "attrs" trực tiếp vào mục nhập biểu mẫu của mình.

ví dụ:

class BlogPostForm(forms.ModelForm):
    title = forms.CharField(label='Title:', max_length=128)
    body = forms.CharField(label='Post:', max_length=2000, 
        widget=forms.Textarea(attrs={'rows':'5', 'cols': '5'}))

    class Meta:
        model = BlogPost
        fields = ('title', 'body')

Thuộc tính "attrs" về cơ bản đi dọc theo đánh dấu HTML sẽ điều chỉnh trường biểu mẫu. Mỗi mục nhập là một bộ của thuộc tính bạn muốn ghi đè và giá trị bạn muốn ghi đè. Bạn có thể nhập bao nhiêu thuộc tính tùy thích miễn là bạn phân tách từng bộ bằng dấu phẩy.


IMO là cách tốt nhất để chỉ sửa đổi một trường duy nhất và không phải tất cả các tiện ích TextInput cùng một lúc (giống như câu trả lời được chấp nhận)
ascripter

7

Cách tốt nhất tôi tìm thấy là một cái gì đó như thế này:

class NotificationForm(forms.ModelForm):
    def __init__(self, *args, **kwargs): 
        super(NotificationForm, self).__init__(*args, **kwargs)
        self.fields['content'].widget.attrs['cols'] = 80
        self.fields['content'].widget.attrs['rows'] = 15
        self.fields['title'].widget.attrs['size'] = 50
    class Meta:
        model = Notification

Nó tốt hơn nhiều cho ModelForm so với việc ghi đè các trường bằng các widget khác nhau, vì nó bảo toàn namehelp_textcác thuộc tính cũng như giá trị mặc định của các trường mô hình, vì vậy bạn không cần phải sao chép chúng vào biểu mẫu của mình.


7

Tôi đã gặp sự cố tương tự với TextField. Tôi đang sử dụng Django 1.0.2 và muốn thay đổi giá trị mặc định cho 'hàng' trong vùng văn bản được liên kết. formfield_overrides không tồn tại trong phiên bản này. Ghi đè formfield_for_dbfield đã hoạt động nhưng tôi phải làm điều đó cho từng lớp con ModelAdmin của mình nếu không sẽ dẫn đến lỗi đệ quy. Cuối cùng, tôi nhận thấy rằng việc thêm mã bên dưới vào models.py hoạt động:

from django.forms import Textarea

class MyTextField(models.TextField):
#A more reasonably sized textarea                                                                                                            
    def formfield(self, **kwargs):
         kwargs.update(
            {"widget": Textarea(attrs={'rows':2, 'cols':80})}
         )
         return super(MyTextField, self).formfield(**kwargs)

Sau đó, sử dụng MyTextField thay vì TextField khi xác định mô hình của bạn. Tôi đã điều chỉnh nó từ câu trả lời này thành một câu hỏi tương tự.


5

Nó được mô tả tốt trong Câu hỏi thường gặp về Django :

H: Làm cách nào để thay đổi các thuộc tính cho tiện ích con trên một trường trong mô hình của tôi?

A: Ghi đè formfield_for_dbfield trong lớp ModelAdmin / StackedInline / TabularInline

class MyOtherModelInline(admin.StackedInline):
    model = MyOtherModel
    extra = 1

    def formfield_for_dbfield(self, db_field, **kwargs):
        # This method will turn all TextFields into giant TextFields
        if isinstance(db_field, models.TextField):
            return forms.CharField(widget=forms.Textarea(attrs={'cols': 130, 'rows':30, 'class': 'docx'}))
        return super(MyOtherModelInline, self).formfield_for_dbfield(db_field, **kwargs)

Khi tôi sử dụng kỹ thuật này, văn bản trợ giúp sẽ không xuất hiện và nếu đó là TabularInline, tiêu đề cột sẽ trở thành 'Không có'.
Steven T. Snyder

1
Đây không phải là một cách tiếp cận tốt, vì bạn đang xóa tất cả các cài đặt khác trong CharField. Ví dụ: theo mặc định, nó sẽ phát hiện một cách thông minh liệu trường biểu mẫu có được yêu cầu hay không, nhưng mã này sẽ phá hủy điều đó. Thay vào đó, bạn nên đặt tiện ích con trên giá trị được trả về bởi lệnh gọi super () của bạn.
Cerin

5

Bạn luôn có thể đặt kích thước trường của mình trong biểu định kiểu tùy chỉnh và yêu cầu Django sử dụng kích thước đó cho lớp ModelAdmin của bạn:

class MyModelAdmin(ModelAdmin):
    class Media:
        css = {"all": ("my_stylesheet.css",)}

câu trả lời tốt nhất! không phải loay hoay với các trường biểu mẫu và thuộc tính (và các tác dụng phụ có thể xảy ra), chỉ cần một tệp css, có thể - với id / lớp hiện có trong biểu mẫu quản trị django - chỉ nhắm mục tiêu một số hoặc thậm chí tất cả các trường một cách dễ dàng. lớn lên!
benzkji

2

cho 1.6, bằng cách sử dụng các biểu mẫu, tôi phải chỉ định các thuộc tính của vùng văn bản bên trong charfield:

test1 = forms.CharField(max_length=400, widget=forms.Textarea( attrs={'rows':'2', 'cols': '10'}),  initial='', help_text=helptexts.helptxt['test'])

1

Câu trả lời tương tự như msdin nhưng với TextInput thay vì TextArea:

from django.forms import TextInput

class ShortTextField(models.TextField):
    def formfield(self, **kwargs):
         kwargs.update(
            {"widget": TextInput(attrs={'size': 10})}
         )
         return super(ShortTextField, self).formfield(**kwargs)

1

Đây là một giải pháp đơn giản nhưng linh hoạt. Sử dụng biểu mẫu tùy chỉnh để ghi đè một số tiện ích con.

# models.py
class Elephant(models.Model):
    name = models.CharField(max_length=25)
    age = models.IntegerField()

# forms.py
class ElephantForm(forms.ModelForm):

    class Meta:
        widgets = {
            'age': forms.TextInput(attrs={'size': 3}),
        }

# admin.py
@admin.register(Elephant)
class ElephantAdmin(admin.ModelAdmin):
    form = ElephantForm

Các widget được cung cấp ElephantFormsẽ thay thế các widget mặc định. Chìa khóa là biểu diễn chuỗi của trường. Các trường không được chỉ định trong biểu mẫu sẽ sử dụng tiện ích con mặc định.

Lưu ý rằng mặc dù agelà một, IntegerFieldchúng ta có thể sử dụng TextInputtiện ích, vì không giống như NumberInput, TextInputchấp nhận sizethuộc tính.

Giải pháp này được mô tả trong bài báo này .


0

Nếu bạn đang làm việc với trường ForeignKey liên quan đến các lựa chọn / tùy chọn / menu thả xuống, bạn có thể ghi đè formfield_for_foreignkeytrong phiên bản Quản trị:

class YourNewAdmin(admin.ModelAdmin):
    ...

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'your_fk_field':
            """ For your FK field of choice, override the dropdown style """
            kwargs["widget"] = django.forms.widgets.Select(attrs={
                'style': 'width: 250px;'
            })

        return super().formfield_for_foreignkey(db_field, request, **kwargs)

Thông tin thêm về mô hình này ở đâyở đây .


-1

Và một ví dụ nữa:

class SecenekInline(admin.TabularInline):
   model = Secenek
   # classes = ['collapse']
   def formfield_for_dbfield(self, db_field, **kwargs):
       field = super(SecenekInline, self).formfield_for_dbfield(db_field, **kwargs)
       if db_field.name == 'harf':
           field.widget = TextInput(attrs={'size':2})
       return field
   formfield_overrides = {
       models.TextField: {'widget': Textarea(attrs={'rows':2})},
   }
   extra = 2

Nếu bạn chỉ muốn chỉnh sửa kích thước trường cụ thể, bạn có thể sử dụng kích thước này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.