2009-05-26 12 views
88

Django ma tendencję do wypełniania przestrzeni poziomej podczas dodawania lub edytowania wpisów na koncie administratora, ale w niektórych przypadkach jest to prawdziwe marnowanie miejsca, np. Edytowanie pola daty o szerokości 8 znaków, lub CharField, również 6 lub 8 znaków szerokich, a następnie pole edycji ma długość do 15 lub 20 znaków.Zmiana rozmiaru pól w Django Admin

Jak mogę poinformować administratora o szerokości pola tekstowego lub wysokości pola edycji TextField?

+0

wiele ciekawych odpowiedzi ... Sprawdzę, co wpisuje się szybciej lub lepiej na moim app, i przyjąć, że: D thx – Andor

+8

Oczywiście, zapomniałem zrobić w tym przypadku. Ponad dwa lata później. =) – casperOne

+0

Projekt został porzucony i przez jakiś czas nie widziałem kodu. Mogę zacząć nowy projekt w przyszłym miesiącu, więc może powtórzę: D – Andor

Odpowiedz

161

Należy wykorzystać ModelAdmin.formfield_overrides.

Jest to dość proste - w admin.py zdefiniować:

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) 

Nie zapominaj, że należy zaimportować odpowiednie klasy - w tym przypadku:

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

To całkiem niezłe rozwiązanie, jeśli sam tak powiem. – jathanism

+0

To było dokładnie to, czego szukałem bez konieczności dokonywania niedorzecznych dostosowań szablonów. Dzięki! – Chris

+1

Zauważ, że to nie zadziała, jeśli parametr 'filter_horizontal' lub' filter_vertical' jest ustawiony dla odpowiednich pól w YourModelAdmin. Spędziłem trochę czasu, aby to zrozumieć. –

41

Możesz ustawić dowolne atrybuty HTML na widżecie, używając jego "attrs" property.

Można to zrobić w panelu administracyjnym przy użyciu 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 

lub z niestandardowym Widget podklasy i formfield_overrides dictionary:

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}} 
21

Szybki i brudny rozwiązaniem jest po prostu dostarczyć niestandardowe szablon dla danego modelu.

Jeśli utworzysz szablon o nazwie admin/<app label>/<class name>/change_form.html, administrator użyje tego szablonu zamiast domyślnego. Oznacza to, że jeśli masz model o nazwie Person w aplikacji o nazwie people, możesz utworzyć szablon o nazwie admin/people/person/change_form.html.

Wszystkie szablony Administrator posiada blok extrahead można przesłonić, aby umieścić rzeczy w <head>, a końcowy element układanki jest fakt, że każde pole ma identyfikator HTML id_<field-name>.

Więc, można umieścić coś jak poniżej w szablonie:

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

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

Szybkie obejście (aby uniknąć niestandardowych rzeczy)! Podoba mi się! – Andor

+0

Dzięki! To i odpowiedź alanjds są bardzo przydatne do zmiany układu interfejsu administratora na podstawie poszczególnych pól, a nie na podstawie typu pola. – nealmcb

10

Jeśli chcesz zmienić atrybuty na przykład za pola, można dodać „attrs” własność bezpośrednio do listy wpisy w formularzu.

na przykład:

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') 

W „attrs” własność w zasadzie przechodzi wzdłuż znaczników HTML, które będą regulować pole formularza. Każdy wpis jest krotką atrybutu, który chcesz zastąpić i wartością, którą chcesz nadpisać. Możesz wprowadzić dowolną liczbę atrybutów, o ile oddzielasz każdą krotkę przecinkiem.

+0

Kolejne interesujące podejście ... – Andor

+0

IMO to najlepszy sposób na modyfikowanie tylko jednego pola, a nie wszystkich widżetów TextInput na raz (jak przyjęta odpowiedź) – ascripter

6

Najlepszym sposobem znalazłem coś takiego:

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 

jej o wiele lepiej dla ModelForm niż przesłanianie pól z różnych widgetów, jak zachowuje name i help_text atrybuty, a także domyślne wartości pól modelu, więc nie musisz ich kopiować do formularza.

5

Jest dobrze opisane w Django FAQ:

Q: Jak zmienić atrybuty dla widgetu na polu w moim modelu?

A: Zastąpić formfield_for_dbfield w klasie 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) 
+0

Gdy używam tej techniki, tekst pomocy nie pojawi się, a jeśli jest a TabularInline, nagłówek kolumny staje się "Brak". –

+1

To nie jest dobre podejście, ponieważ usuwasz wszystkie inne ustawienia w CharField. Na przykład domyślnie inteligentnie wykryje, czy pole formularza powinno być wymagane, ale ten kod niszczy to. Zamiast tego należy ustawić widget na wartość zwracaną przez swoje połączenie super(). – Cerin

7

miałem podobny problem z Pole tekstowe. Używam Django 1.0.2 i chciałem zmienić domyślną wartość dla "wierszy" w powiązanym textarea. formfield_overrides nie istnieje w tej wersji. Przesłonięcie pola formfield_for_dbfield zadziałało, ale musiałem to zrobić dla każdej z podklas ModelAdmin, co spowodowałoby błąd rekursji. W końcu stwierdziliśmy, że dodanie poniższego kodu do models.py prace:

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) 

Następnie użyj myTextField zamiast TextField przy definiowaniu modeli. Zaadaptowałem to z this answer na podobne pytanie.

+0

Bravo! to jest najprostsze podejście –

5

Zawsze można ustawić pola wymiarów niestandardowych stylów i poinformować Django w obsłudze, że dla swojej klasy ModelAdmin:

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

najlepsza odpowiedź! bez błahostowania z polami formularzy i atrybutami (i możliwymi efektami ubocznymi), po prostu plik css, który może - z istniejącymi ids/classes w formularzach admin django - łatwo atakować tylko niektóre, a nawet wszystkie pola. duże! – benzkji

1

samą odpowiedź jak msdin ale z TextInput zamiast 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) 
2

dla wersji 1.6, używając formularzy musiałem określić atrybuty textarea wewnątrz charfield:

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

To nie działa dla 'TextField'. –

18

Aby zmienić szerokość określonego pola.

Wykonane przez 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 
+0

Moim zdaniem jest to najlepsza odpowiedź, ponieważ pozwala na zmianę poszczególnych pól bez konieczności tworzenia nowego formularza. – rbennell