web-dev-qa-db-fra.com

Django Admin - Remplacer le widget d'un champ de formulaire personnalisé

J'ai un champ de formulaire TagField personnalisé.

class TagField(forms.CharField):
    def __init__(self, *args, **kwargs):
        super(TagField, self).__init__(*args, **kwargs)
        self.widget = forms.TextInput(attrs={'class':'tag_field'})

Comme vu ci-dessus, il utilise un widget de champ de formulaire TextInput. Mais en admin, je voudrais qu'il soit affiché en utilisant le widget Textarea. Pour cela, il y a formfield_overrides hook mais cela ne fonctionne pas dans ce cas.

La déclaration d'administration est:

class ProductAdmin(admin.ModelAdmin):
    ...
    formfield_overrides = {
        TagField: {'widget': admin.widgets.AdminTextareaWidget},
    }

Cela n'a aucun effet sur le widget de champ de formulaire et tags sont toujours rendus avec un widget TextInput.

Toute aide est très appréciée.

-
omat

31
onurmatik

L'administrateur Django utilise des widgets personnalisés pour bon nombre de ses champs. La façon de remplacer les champs consiste à créer un formulaire à utiliser avec l'objet ModelAdmin.

# forms.py

from Django import forms
from Django.contrib import admin

class ProductAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ProductAdminForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = admin.widgets.AdminTextareaWidget()

Ensuite, dans votre objet ModelAdmin, vous spécifiez la forme:

from Django.contrib import admin
from models import Product
from forms import ProductAdminForm

class ProductAdmin(admin.ModelAdmin):
    form = ProductAdminForm

admin.site.register(Product, ProductAdmin)

Vous pouvez également remplacer le jeu de requêtes à ce stade: pour filtrer les objets en fonction d'un autre champ du modèle, par exemple (puisque limit_choices_to ne peut pas gérer cela)

45
Matthew Schinckel

Vous pouvez remplacer les widgets de champ en étendant la classe Meta ModelForm depuis Django 1.2:

class ProductAdminForm(forms.ModelForm):
    class Meta:
        model = Product
        widgets = {
            'tags': admin.widgets.AdminTextareaWidget
        }

class ProductAdmin(admin.ModelAdmin):
    form = ProductAdminForm

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-fields

34
Murat Çorlu

Essayez de changer votre domaine comme ceci:

class TagField(forms.CharField):
    def __init__(self, *args, **kwargs):
        self.widget = forms.TextInput(attrs={'class':'tag_field'})
        super(TagField, self).__init__(*args, **kwargs)

Cela permettrait d'utiliser le widget qui vient de **kwargs. Sinon, votre champ utilisera toujours form.TextInput widget.

2
Andrey Fedoseev

Pour un champ spécifique et non une sorte de champs que j'utilise:

Django 2.1.7

class ProjectAdminForm(forms.ModelForm):
    class Meta:
        model = Project
        fields = '__all__'
        widgets = {
            'project_description': forms.Textarea(attrs={'cols': 98})
        }
class ProjectAdmin(admin.ModelAdmin):
    form = ProjectAdminForm

Merci, @Murat Çorlu

0
C.K.