Redimensionner les champs dans Django Admin

Django a tendance à remplir l'espace horizontal lors de l'ajout ou de l'édition d'entrées sur l'administrateur, mais, dans certains cas, est un véritable gaspillage d'espace, lorsque, c'est-à-dire, éditer un champ de date, 8 caractères de large, ou un CharField, aussi 6 ou 8 caractères de large, puis la zone d'édition va jusqu'à 15 ou 20 caractères.

Comment puis-je indiquer à l'administrateur la largeur d'une zone de texte ou la hauteur d'une zone D'édition de champ de texte?

94
demandé sur Gringo Suave 2009-05-26 15:16:16

11 réponses

, Vous devez utiliser ModelAdmin.formfield_overrides.

C'est assez facile-dans admin.py, Définissez:

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)

N'oubliez pas que vous devez importer les classes appropriées, dans ce cas:

from django.forms import TextInput, Textarea
from django.db import models
175
répondu jki 2013-09-30 17:01:24

Vous pouvez définir des attributs HTML arbitraires sur un widget en utilisant sa propriété "attrs" .

Vous pouvez le faire dans L'administrateur Django en utilisant 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

Ou avec une sous-classe de Widget personnalisée et le dictionnaire 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}}
41
répondu Carl Meyer 2010-08-16 18:44:35

Une option rapide et sale consiste simplement à fournir un modèle personnalisé pour le modèle en question.

Si vous créez un modèle nommé admin/<app label>/<class name>/change_form.html, l'administrateur utilisera ce modèle au lieu du modèle par défaut. C'est, si vous avez un modèle nommé Person dans une application nommée people, vous devez créer un modèle nommé admin/people/person/change_form.html.

Tous les modèles d'administration ont un bloc extrahead que vous pouvez remplacer pour placer des éléments dans le <head>, et la dernière pièce du puzzle est le fait que chaque champ a un identifiant HTML de id_<field-name>.

Donc, vous pouvez mettre quelque chose comme ce qui suit dans votre modèle:

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

{% block extrahead %}
  {{ block.super }}
  <style type="text/css">
    #id_my_field { width: 100px; }
  </style>
{% endblock %}
21
répondu jacobian 2009-05-26 20:45:00

Pour modifier la largeur d'un champ spécifique.

Fait via 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
20
répondu alanjds 2015-12-15 13:16:07

Si vous souhaitez modifier les attributs sur une instance par champ, vous pouvez ajouter la propriété" attrs " directement dans vos entrées de formulaire.

Par exemple:

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 propriété" attrs " passe essentiellement le long du balisage HTML qui ajustera le champ de formulaire. Chaque entrée est un n-uplet de l'attribut que vous souhaitez remplacer et de la valeur que vous souhaitez la remplacer par. Vous pouvez entrer autant d'attributs que vous le souhaitez tant que vous séparez chaque tuple avec une virgule.

10
répondu Jonathan 2009-05-27 01:36:50

La meilleure façon que j'ai trouvée est quelque chose comme ceci:

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

C'est beaucoup mieux pour ModelForm que de surcharger les champs avec des widgets différents, car il préserve les attributs name et help_text ainsi que les valeurs par défaut des champs de modèle, vous n'avez donc pas besoin de les copier dans votre formulaire.

7
répondu kurczak 2009-08-09 17:58:57

J'ai eu un problème similaire avec TextField. J'utilise Django 1.0.2 et je voulais changer la valeur par défaut pour 'rows' dans la zone de texte associée. formfield_overrides n'existe pas dans cette version. La substitution de formfield_for_dbfield a fonctionné mais je devais le faire pour chacune de mes sous-classes ModelAdmin ou cela entraînerait une erreur de récursivité. Finalement, j'ai trouvé que l'ajout du code ci-dessous à models.py travaux:

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)

Ensuite, utilisez MyTextField au lieu de TextField lors de la définition de vos modèles. Je adapté de cette réponse à une question similaire.

7
répondu msdin 2017-05-23 10:31:13

C'est bien décrit dans Django FAQ :

Q: Comment modifier les attributs d'un widget sur un champ de mon modèle?

A: remplace le champ formfield_for_dbfield dans la 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)
5
répondu HardQuestions 2009-09-02 15:02:06

Vous pouvez toujours définir la taille de vos champs dans une feuille de style personnalisée et dire à Django de l'utiliser pour votre classe ModelAdmin:

class MyModelAdmin(ModelAdmin):
    class Media:
        css = {"all": ("my_stylesheet.css",)}
5
répondu Gonzalo Delgado 2010-01-26 09:11:02

Pour 1.6, en utilisant des formulaires, je devais spécifier les attributs de la zone de texte à l'intérieur du charfield:

test1 = forms.CharField(max_length=400, widget=forms.Textarea( attrs={'rows':'2', 'cols': '10'}),  initial='', help_text=helptexts.helptxt['test'])
2
répondu deddu 2013-03-27 02:10:18

Même réponse que msdin mais avec TextInput au lieu de 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
répondu dan-klasson 2011-12-18 15:04:13