4 votes

Comment manipuler les champs de formulaire dans Django dynamiquement dans ModelAdmin ?

J'ai un champ (slug) qui est "obligatoire" dans le modèle, mais je veux changer le champ dans la classe ModelAdmin pour qu'il soit optionnel. Si l'utilisateur ne le remplit pas, il est automatiquement rempli par un autre champ (name).

class SomeModel(model.Model):
  name = model.CharField(max_length=255)
  slug = model.SlugField(unique=True, max_length=255)

J'ai essayé de le faire de différentes manières, notamment en remplaçant get_form() dans ModelAdmin ou en utilisant la classe ModelForm et en spécifiant le formulaire de manière spécifique.

class SomeModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(self.__class__, self).get_form(request, obj, **kwargs)
        form.slug.required = False
        return form

Cependant, aucune de ces deux solutions n'a fonctionné pour moi. Outre la création manuelle du formulaire, existe-t-il une autre solution plus rapide ?

J'ai beaucoup de ces formulaires, et le faire à la main pourrait être fastidieux et difficile à maintenir.

5voto

Eric P Points 424

J'ai trouvé cette page sur Google alors que je me débattais avec le même problème. Ce qui suit fonctionnera également dans le ModelAdmin :

def get_form(self, *args, **kwargs):
    form = super(SomeModelAdmin, self).get_form(*args, **kwargs)
    form.base_fields['slug'].required = False
    return form

Les formulaires ultérieurs créés à partir de la version actualisée du ModelFormMetaclass aura la slug domaine non requis.

Cela fonctionne mieux dans mon cas, où je n'ai qu'une seule classe dans laquelle je dois libérer le champ, et où je n'ai pas besoin de faire de transformation de données lors de l'enregistrement. La solution de GoogleDroid est meilleure si vous avez beaucoup de classes, ou si les transformations de données sont nécessaires.

1voto

Daniel Roseman Points 199743

Dans votre get_form méthode, form.fields['slug'].required devrait fonctionner.

Mais la meilleure façon de procéder est de fournir un ModelForm personnalisé.

class SomeModelForm(forms.ModelForm):
    slug = forms.CharField(required=False)

class SomeModelAdmin(admin.ModelAdmin):
    form = SomeModelForm

Par ailleurs, ne faites pas super(self.__class__, self) . Vous devez toujours nommer explicitement la classe courante lorsque vous utilisez la fonction super sinon toute sous-classe qui hérite de la vôtre et appelle à son tour super se brisera.

Editar form.fields , pas forms.fields .

En disant self.__class__ Vous empêchez explicitement Python d'élaborer l'héritage, car il se réfère toujours à la classe concrète, c'est-à-dire à la base de l'arbre d'héritage. Mais si votre méthode se trouve au milieu de cet arbre, alors le fait de se référer à la classe concrète en super est erroné - parce que vous voulez qu'il appelle le niveau supérieur à celui où vous vous trouvez, et non pas le niveau supérieur à celui où vous vous trouvez. C'est pourquoi vous devez toujours nommer la classe dans laquelle vous vous trouvez - dans ce cas, super(SomeModelAdmin, self) .

1voto

GoogleDroid Points 165

Je voulais juste faire un rapport au cas où d'autres personnes trouveraient cela utile.

Je n'ai jamais été en mesure de get_form méthode faire form.fields['slug'].required et n'a jamais compris pourquoi. Cependant, j'ai résolu mon problème en créant un nouveau formulaire héritant de ModelForm.

J'ai dû passer outre init () pour régler self.fields['slug'].required = False après avoir appelé le constructeur parent, puis surcharger clean_slug() de modifier le contenu du champ "slug" si nécessaire en accédant à self.data['slug'] .

J'espère que cela aidera quelqu'un

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X