web-dev-qa-db-de.com

Django Admin: Verwenden eines benutzerdefinierten Widgets für nur ein Modellfeld

Ich habe ein DateTimeField Feld in meinem Modell. Ich wollte es als Kontrollkästchen-Widget auf der Django admin-Site anzeigen. Dazu habe ich ein benutzerdefiniertes Formular-Widget erstellt. Ich weiß jedoch nicht, wie ich mein benutzerdefiniertes Widget für Folgendes verwenden soll: nur dieses eine Feld.

In der Django-Dokumentation wird erklärt, wie ein benutzerdefiniertes Widget für alle Felder eines bestimmten Typs verwendet wird:

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

Dies ist jedoch nicht granular genug. Ich möchte es nur für eins Feld ändern.

58

Erstellen Sie eine benutzerdefinierte ModelForm für Ihren ModelAdmin und fügen Sie der Meta-Klasse Widgets wie folgt hinzu:

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

class StopAdmin(admin.ModelAdmin):
  form = StopAdminForm

Erledigt!

Die Dokumentation hierfür ist in den ModelForm-Dokumenten sozusagen nicht intuitiv abgelegt, ohne dass dies in den Admin-Dokumenten erwähnt wird. Siehe: Formulare aus Modellen erstellen

120
Chris Pratt

Nachdem ich mich in den Code admin , model field und form field vertieft habe, glaube ich, dass die einzige Möglichkeit, das zu tun, was ich will, darin besteht, eine Benutzerdefinition zu erstellen Modellfeld:

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

Es wird die Arbeit erledigt.

Vorerst werde ich die Frage unbeantwortet lassen, weil ich die Angewohnheit habe, das Offensichtliche zu verpassen. Vielleicht haben einige Django smartypants eine bessere Lösung.

31

Überschreibe formfield_for_dbfield wie folgt:

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)

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

18
Andy Baker

Djangos ModelAdmin.get_changelist_form (self, request, ** kwargs) erledigt den Trick für den Fall 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

Siehe Offizielle Django-Dokumentation zu diesem Thema

Ich hoffe das wird helfen

4
Arya-2790306