web-dev-qa-db-fra.com

Django Admin: utilisation d'un widget personnalisé pour un seul champ de modèle

J'ai un champ DateTimeField dans mon modèle. Je voulais l'afficher en tant que widget de case à cocher dans le site d'administration Django. Pour ce faire, j'ai créé un widget de formulaire personnalisé. Cependant, je ne sais pas comment utiliser mon widget personnalisé pour seulement ce seul champ.

La documentation Django explique comment utiliser un widget personnalisé pour tous les champs d'un certain type:

class StopAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.DateTimeField: {'widget': ApproveStopWidget }
    }

Ce n'est cependant pas assez granulaire. Je veux le changer pour seulement un champ.

58
Belmin Fernandez

Créez un ModelForm personnalisé pour votre ModelAdmin et ajoutez des "widgets" à sa classe Meta, comme ceci:

class StopAdminForm(forms.ModelForm):
  class Meta:
    model = Stop
    widgets = {
      'approve_ts': ApproveStopWidget(),
    }
    fields = '__all__'

class StopAdmin(admin.ModelAdmin):
  form = StopAdminForm

Terminé!

La documentation pour cela est en quelque sorte placée de manière non intuitive dans les documents ModelForm, sans aucune mention à ce sujet dans les documents d'administration. Voir: Création de formulaires à partir de modèles

120
Chris Pratt

Après avoir creusé dans le code admin , champ modèle et champ formulaire , je crois que la seule façon de réaliser ce que je veux est de créer un personnalisé champ modèle:

models.py

from Django.db import models
from widgets import ApproveStopWidget

class ApproveStopModelField(models.DateTimeField):
    pass

class Stop(models.model):
    # Other fields
    approve_ts = ApproveStopModelField('Approve place', null=True, blank=True)

admin.py

from widgets import ApproveStopWidget
from models import ApproveStopModelField

class StopAdmin(admin.ModelAdmin):
    formfield_overrides = {
        ApproveStopModelField: {'widget': ApproveStopWidget }
    }

Il fait le travail.

Pour l'instant, je vais laisser la question sans réponse car j'ai l'habitude de manquer l'évidence. Certains Django smartypants ont peut-être une meilleure solution.

31
Belmin Fernandez

Remplacez formfield_for_dbfield comme ceci:

class VehicleAdmin(admin.ModelAdmin):
  search_fields = ["name", "colour"]
  def formfield_for_dbfield(self, db_field, **kwargs):
    if db_field.name == 'colour':
      kwargs['widget'] = ColourChooserWidget
    return super(VehicleAdmin,self).formfield_for_dbfield(db_field,**kwargs)

(crédit à http://www.kryogenix.org/days/2008/03/28/overriding-a-single-field-in-the-Django-admin-using-newforms-admin/ )

18
Andy Baker

Le ModelAdmin.get_changelist_form de Django (self, request, ** kwargs) fera l'affaire pour le cas de list_editable

class StopAdminForm(forms.ModelForm):
  class Meta:
    model = Stop
    widgets = {
      'approve_ts': ApproveStopWidget(),
    }

class StopAdmin(admin.ModelAdmin):
  form = StopAdminForm

  #just return the ModelForm class StopAdminForm
  def get_changelist_form(self, request, **kwargs):
        return StopAdminForm

Reportez-vous à documentation officielle de Django sur ce sujet

J'espère que cela vous aidera

4
Arya-2790306