Ridimensiona i campi in Django Admin


107

Django tende a riempire lo spazio orizzontale quando si aggiungono o si modificano voci sull'amministratore, ma, in alcuni casi, è un vero spreco di spazio, quando, ad esempio, si modifica un campo data, largo 8 caratteri, o un CharField, anche 6 o 8 caratteri di larghezza, quindi la casella di modifica arriva fino a 15 o 20 caratteri.

Come posso dire all'amministratore quanto dovrebbe essere larga una casella di testo o l'altezza di una casella di modifica TextField?


9
Ovviamente, ti sei dimenticato di farlo in questo caso. Più di due anni dopo. =)
casper Il

Il progetto è stato abbandonato e per un po 'non ho potuto vedere il codice. Potrei iniziare un nuovo progetto il mese prossimo, quindi forse lo rivedrò: D
Andor

Risposte:


209

Dovresti usare ModelAdmin.formfield_overrides .

È abbastanza facile - in admin.py, definire:

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
Questo era esattamente quello che stavo cercando senza dover apportare alcune ridicole personalizzazioni dei modelli. Grazie!
Chris,

2
Tieni presente che questo non funzionerà se filter_horizontalo filter_verticalè impostato per i campi corrispondenti in YourModelAdmin. Ho passato un po 'di tempo a capirlo.
Dennis Golomazov

C'è qualcosa di strano in una forma? Non ho trovato un modo per impostare l'attributo attrs per tutte le aree di testo.
Julian,

1
Ho usato solo models.TextField: {'widget': Textarea(attrs={'rows':4})}ma anche la larghezza è diventata più piccola.
Smit Johnth

Apparentemente è difficile averli delle stesse dimensioni.
Sören

44

È possibile impostare attributi HTML arbitrari su un widget utilizzando la sua proprietà "attrs" .

Puoi farlo nell'amministratore di Django usando 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

o con una sottoclasse Widget personalizzata e il dizionario 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

Per modificare la larghezza per un campo specifico.

Realizzato tramite 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

Secondo me questa è la risposta migliore, poiché consente di modificare i singoli campi senza dover creare un nuovo modulo.
rbennell

20

Un'opzione rapida e sporca è semplicemente fornire un modello personalizzato per il modello in questione.

Se crei un modello denominato, admin/<app label>/<class name>/change_form.htmll'amministratore utilizzerà quel modello anziché quello predefinito. Cioè, se hai un modello denominato Personin un'app denominata people, creerai un modello denominato admin/people/person/change_form.html.

Tutti i modelli di amministrazione hanno un extraheadblocco che puoi sovrascrivere per inserire elementi in <head>, e l'ultimo pezzo del puzzle è il fatto che ogni campo ha un ID HTML di id_<field-name>.

Quindi, potresti inserire qualcosa di simile nel tuo modello:

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

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

Grazie! Questa e la risposta di alanjds sono molto utili per modificare il layout nell'interfaccia di amministrazione in base al campo, piuttosto che in base al tipo di campo.
nealmcb

10

Se desideri modificare gli attributi su un'istanza per campo, puoi aggiungere la proprietà "attrs" direttamente alle voci del modulo.

per esempio:

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

La proprietà "attrs" fondamentalmente passa lungo il markup HTML che regolerà il campo del modulo. Ogni voce è una tupla dell'attributo che si desidera sovrascrivere e il valore con cui si desidera sovrascriverlo. Puoi inserire tutti gli attributi che desideri purché separa ogni tupla con una virgola.


IMO il modo migliore per modificare solo un singolo campo e non tutti i widget TextInput contemporaneamente (come fa la risposta accettata)
ascritto

7

Il modo migliore che ho trovato è qualcosa del genere:

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

È molto meglio per ModelForm che sovrascrivere i campi con widget diversi, poiché conserva namee help_textattributi e anche i valori predefiniti dei campi del modello, quindi non è necessario copiarli nel modulo.


7

Ho avuto un problema simile con TextField. Sto usando Django 1.0.2 e volevo cambiare il valore predefinito per "righe" nella textarea associata. formfield_overrides non esiste in questa versione. L'override di formfield_for_dbfield ha funzionato, ma ho dovuto farlo per ciascuna delle mie sottoclassi ModelAdmin o avrebbe generato un errore di ricorsione. Alla fine, ho scoperto che l'aggiunta del codice seguente a models.py funziona:

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)

Quindi usa MyTextField invece di TextField quando definisci i tuoi modelli. L'ho adattato da questa risposta a una domanda simile.


5

È ben descritto nelle FAQ di Django :

D: Come si modificano gli attributi di un widget su un campo nel mio modello?

R: Sostituisci formfield_for_dbfield nella classe 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)

Quando utilizzo questa tecnica, il testo della guida non viene visualizzato e, se è un TabularInline, l'intestazione della colonna diventa "Nessuno".
Steven T.Snyder

1
Questo non è un buon approccio, poiché stai cancellando tutte le altre impostazioni in CharField. Ad esempio, per impostazione predefinita, rileverà in modo intelligente se il campo del modulo deve essere richiesto o meno, ma questo codice lo distrugge. Dovresti invece impostare il widget sul valore restituito dalla tua chiamata super ().
Cerin

5

Puoi sempre impostare le dimensioni dei tuoi campi in un foglio di stile personalizzato e dire a Django di usarlo per la tua classe ModelAdmin:

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

migliore risposta! non giocherellare con campi e attributi (e possibili effetti collaterali), solo un file css, che può - con gli id ​​/ classi esistenti nei moduli di amministrazione di django - indirizzare facilmente solo alcuni o anche tutti i campi. grande!
benzkji

2

per 1.6, usando i form ho dovuto specificare gli attributi della textarea all'interno del charfield:

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

1

Stessa risposta di msdin ma con TextInput invece di 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

Ecco una soluzione semplice ma flessibile. Usa un modulo personalizzato per sovrascrivere alcuni widget.

# 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

I widget forniti ElephantFormsostituiranno quelli predefiniti. La chiave è la rappresentazione di stringa del campo. I campi non specificati nel modulo utilizzeranno il widget predefinito.

Nota che sebbene agesia un IntegerFieldpossiamo usare il TextInputwidget, perché a differenza di NumberInput, TextInputaccetta l' sizeattributo.

Questa soluzione è descritta in questo articolo .


0

Se stai lavorando con un campo ForeignKey che coinvolge scelte / opzioni / un menu a discesa, puoi eseguire l'override formfield_for_foreignkeynell'istanza di amministrazione:

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)

Maggiori informazioni su questo modello qui e qui .


-1

E anche un altro esempio:

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

Se vuoi modificare solo una dimensione specifica dei campi, puoi usarla.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.