Django füllt beim Hinzufügen oder Bearbeiten von Einträgen im Admin normalerweise den horizontalen Bereich aus. In manchen Fällen ist dies jedoch eine echte Platzverschwendung, wenn z. B. ein Datumsfeld mit einer Breite von 8 Zeichen oder ein CharField mit 6 oder 8 bearbeitet wird Zeichen breit, und dann geht das Editierfeld auf 15 oder 20 Zeichen.
Wie kann ich dem Administrator mitteilen, wie breit ein Textfeld sein soll oder wie hoch ein TextField-Bearbeitungsfeld ist?
Sie sollten ModelAdmin.formfield_overrides verwenden.
Es ist ziemlich einfach - in admin.py
definieren Sie:
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)
Vergessen Sie nicht, dass Sie geeignete Klassen importieren sollten - in diesem Fall:
from Django.forms import TextInput, Textarea
from Django.db import models
Sie können beliebige HTML-Attribute für ein Widget festlegen, indem Sie die Eigenschaft "attrs" verwenden.
Sie können dies im Django-Administrator mit formfield_for_dbfield tun:
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
oder mit einer benutzerdefinierten Widget-Unterklasse und dem Wörterbuch 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}}
Eine schnelle und unpassende Option besteht darin, einfach eine benutzerdefinierte Vorlage für das betreffende Modell bereitzustellen.
Wenn Sie eine Vorlage mit dem Namen admin/<app label>/<class name>/change_form.html
erstellen, verwendet der Administrator diese Vorlage anstelle der Standardeinstellung. Wenn Sie also ein Modell mit dem Namen Person
in einer App mit dem Namen people
haben, erstellen Sie eine Vorlage mit dem Namen admin/people/person/change_form.html
.
Alle Admin-Vorlagen haben einen extrahead
-Block, den Sie überschreiben können, um Sachen in <head>
zu platzieren. Der letzte Teil des Puzzles ist die Tatsache, dass jedes Feld eine HTML-ID mit id_<field-name>
hat.
So könnten Sie etwa Folgendes in Ihre Vorlage einfügen:
{% extends "admin/change_form.html" %}
{% block extrahead %}
{{ block.super }}
<style type="text/css">
#id_my_field { width: 100px; }
</style>
{% endblock %}
Zum Ändern der Breite für ein bestimmtes Feld.
Erstellt über 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
Wenn Sie die Attribute in einer Instanz pro Feld ändern möchten, können Sie die Eigenschaft "attrs" direkt in Ihre Formulareinträge einfügen.
zum Beispiel:
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')
Die "attrs" -Eigenschaft übergibt im Wesentlichen das HTML-Markup, mit dem das Formularfeld angepasst wird. Jeder Eintrag ist ein Tupel des Attributs, das Sie überschreiben möchten, und den Wert, mit dem Sie es überschreiben möchten. Sie können so viele Attribute eingeben, wie Sie möchten, solange Sie jeden Tupel mit einem Komma trennen.
Der beste Weg, den ich gefunden habe, ist etwa so:
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
Es ist viel besser für ModelForm als das Überschreiben von Feldern mit verschiedenen Widgets, da dabei name
- und help_text
-Attribute sowie Standardwerte von Modellfeldern beibehalten werden, sodass Sie sie nicht in Ihr Formular kopieren müssen.
Ich hatte ein ähnliches Problem mit TextField. Ich verwende Django 1.0.2 und wollte den Standardwert für 'Zeilen' im zugehörigen Textbereich ändern. formfield_overrides existiert in dieser Version nicht. Das Überschreiben von formfield_for_dbfield hat funktioniert, aber ich musste es für jede meiner ModelAdmin-Unterklassen tun, da dies einen Rekursionsfehler zur Folge hatte. Schließlich fand ich, dass das Hinzufügen des folgenden Codes zu models.py funktioniert:
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)
Verwenden Sie dann MyTextField anstelle von TextField, wenn Sie Ihre Modelle definieren. Ich habe es von dieser Antwort auf eine ähnliche Frage angepasst.
Sie können die Größe der Felder immer in einem benutzerdefinierten Stylesheet festlegen und Django anweisen, diese für Ihre ModelAdmin-Klasse zu verwenden:
class MyModelAdmin(ModelAdmin):
class Media:
css = {"all": ("my_stylesheet.css",)}
Es ist gut beschrieben in Django FAQ :
F: Wie ändere ich die Attribute für ein Widget in einem Feld in meinem Modell?
A: Überschreibt das Feld formfield_for_db in der Klasse 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)
für 1.6 musste ich unter Verwendung von Formularen die Attribute des Textbereichs innerhalb des Zeichenfelds angeben:
test1 = forms.CharField(max_length=400, widget=forms.Textarea( attrs={'rows':'2', 'cols': '10'}), initial='', help_text=helptexts.helptxt['test'])
Gleiche Antwort wie msdin, jedoch mit TextInput statt 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)
Und noch ein Beispiel:
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
Wenn Sie nur eine bestimmte Feldgröße bearbeiten möchten, können Sie diese verwenden.
Wenn Sie mit einem ForeignKey-Feld arbeiten, das Auswahlmöglichkeiten/Optionen/ein Dropdown-Menü enthält, können Sie formfield_for_foreignkey
in der Admin-Instanz überschreiben:
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)
Hier ist eine einfache und dennoch flexible Lösung. Verwenden Sie ein benutzerdefiniertes Formular, um einige Widgets zu überschreiben.
# 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
Die in ElephantForm
angegebenen Widgets ersetzen die Standard-Widgets. Der Schlüssel ist die Zeichenfolgendarstellung des Feldes. Felder, die nicht im Formular angegeben sind, verwenden das Standard-Widget.
Obwohl age
eine IntegerField
ist, können wir das TextInput
-Widget verwenden, da NumberInput
anders als TextInput
das size
-Attribut akzeptiert.
Diese Lösung wird in in diesem Artikel beschrieben.