Django-fr

Forum

#1 29-09-2010 15:23:59

ark
Membre
Inscription : 29-09-2010
Messages : 8

Accéder aux champs dans add_view()

Bonjour,

Je voudrais modifier le champ d'une classe lors de l'affichage de la form dans l'admin.
J'utilise donc la méthode add_view() dans le ModelAdmin, mais je ne trouve pas comme accéder aux champs pour modifier leurs propriétés.

Merci!

Hors ligne

#2 29-09-2010 17:01:07

David Thenon
Membre
Inscription : 11-08-2010
Messages : 156
Site Web

Re : Accéder aux champs dans add_view()

Salut,

Qu'on me corrige si je me trompe mais add_view() est pas fait pour contrôler
le formulaire du modèle mais seulement sa vue (enfin "view").

Pour bidouiller le formulaire admin tu peux plutôt te pencher vers "get_form"
:
http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L348

Tu peux déja y contrôler la visibilité des champs par exemple en les virant de
"self.fieldsets" (ça je sais que ça marche je le fais déja).

En espérant t'avoir donné une piste fructueuse.

Cordialement,
THENON David.

Le mercredi 29 septembre 2010 16:24:00, ark a écrit :
> Bonjour,
>
> Je voudrais modifier le champ d'une classe lors de l'affichage de la form
> dans l'admin.
> J'utilise donc la méthode add_view() dans le ModelAdmin, mais je ne
> trouve pas comme accéder aux champs pour modifier leurs propriétés.
>
> Merci!
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
> ---------------------------------------------------------------------------
> ------------ Orange vous informe que cet  e-mail a ete controle par
> l'anti-virus mail. Aucun virus connu a ce jour par nos services n'a ete
> detecte.

Hors ligne

#3 29-09-2010 17:25:17

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Accéder aux champs dans add_view()

ark,

Il peut aussi être plus simple d'utiliser l'option form de ModelAdmin
[1] : tu peux la modifier pour affecter à la fois la vue pour la
modification et l'ajout ou bien le modifier uniquement dans la methode
add_view en dans ce cas sur self.form.

Peut-être qu'en expliquant la nature du changement à apporter nous
pourrons être plus précis.

[1]
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form

Hors ligne

#4 29-09-2010 17:47:37

David Thenon
Membre
Inscription : 11-08-2010
Messages : 156
Site Web

Re : Accéder aux champs dans add_view()

Ca semble effectivement la meilleure idée, j'avais jamais tilté la dessus et
comme c'est un ModelForm, en théorie il doit pas avoir quoique ce soit à re-
déclarer si ce n'est ses méthodes et attributs spécifiques.

Le mercredi 29 septembre 2010 18:25:17, werefr0g a écrit :
>   ark,
>
> Il peut aussi être plus simple d'utiliser l'option form de ModelAdmin
> [1] : tu peux la modifier pour affecter à la fois la vue pour la
> modification et l'ajout ou bien le modifier uniquement dans la methode
> add_view en dans ce cas sur self.form.
>
> Peut-être qu'en expliquant la nature du changement à apporter nous
> pourrons être plus précis.
>
> [1]
> http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admi
> n.ModelAdmin.form
>
>
>
> ---------------------------------------------------------------------------
> ------------ Orange vous informe que cet  e-mail a ete controle par
> l'anti-virus mail. Aucun virus connu a ce jour par nos services n'a ete
> detecte.

Hors ligne

#5 29-09-2010 17:49:56

Rémy HUBSCHER
Membre
Inscription : 11-08-2010
Messages : 161

Re : Accéder aux champs dans add_view()

Tu as aussi la propriété add_form qui te permet de faire un ModelForm
différent pour l'ajout et la modification.

Le mercredi 29 septembre 2010 à 18:47 +0200, David THENON a écrit :
> Ca semble effectivement la meilleure idée, j'avais jamais tilté la dessus et
> comme c'est un ModelForm, en théorie il doit pas avoir quoique ce soit à re-
> déclarer si ce n'est ses méthodes et attributs spécifiques.
>
> Le mercredi 29 septembre 2010 18:25:17, werefr0g a écrit :
> >   ark,
> >
> > Il peut aussi être plus simple d'utiliser l'option form de ModelAdmin
> > [1] : tu peux la modifier pour affecter à la fois la vue pour la
> > modification et l'ajout ou bien le modifier uniquement dans la methode
> > add_view en dans ce cas sur self.form.
> >
> > Peut-être qu'en expliquant la nature du changement à apporter nous
> > pourrons être plus précis.
> >
> > [1]
> > http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admi
> > n.ModelAdmin.form
> >
> >
> >
> > ---------------------------------------------------------------------------
> > ------------ Orange vous informe que cet  e-mail a ete controle par
> > l'anti-virus mail. Aucun virus connu a ce jour par nos services n'a ete
> > detecte.
>
>
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django

Hors ligne

#6 29-09-2010 17:57:23

ark
Membre
Inscription : 29-09-2010
Messages : 8

Re : Accéder aux champs dans add_view()

Effectivement l'option form est peut-être + faite pour ça.
En fait je voudrais bloquer une liste de choix sur un élément (en espérant que ce soit possible)

Merci pour votre aide

Hors ligne

#7 29-09-2010 18:57:34

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Accéder aux champs dans add_view()

Le 29/09/2010 18:49, Rémy Hubscher a écrit :
> Tu as aussi la propriété add_form qui te permet de faire un ModelForm
> différent pour l'ajout et la modification.
Rémi,

Avant de répondre, j'ai cherché si add_form est disponible : j'ai bien
trouvé add_form_template mais aucune trace de add_form si ce n'est du
côté de auth. hmm Serais-tu assez aimable pour y trainer ma vieille
carcasse ?

Merci.

Hors ligne

#8 29-09-2010 19:18:57

Rémy HUBSCHER
Membre
Inscription : 11-08-2010
Messages : 161

Re : Accéder aux champs dans add_view()

J'ai bien fait d'en parler.

En fait ce n'est pas "encore" documenté vraissemblablement.

Moi j'ai regardé le code de UserAdmin pour "apprendre"

django/contrib/auth/admin.py l.40 :

    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm
    list_display = ('username', 'email', 'first_name', 'last_name',
'is_staff')
    list_filter = ('is_staff', 'is_superuser', 'is_active')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)
    filter_horizontal = ('user_permissions',)

Bon courage,

Rémy

Le mercredi 29 septembre 2010 à 19:57 +0200, werefr0g a écrit :
>
>
> Le 29/09/2010 18:49, Rémy Hubscher a écrit :
> > Tu as aussi la propriété add_form qui te permet de faire un ModelForm
> > différent pour l'ajout et la modification.
> Rémi,
>
> Avant de répondre, j'ai cherché si add_form est disponible : j'ai bien
> trouvé add_form_template mais aucune trace de add_form si ce n'est du
> côté de auth. hmm Serais-tu assez aimable pour y trainer ma vieille
> carcasse ?
>
> Merci.
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django

Hors ligne

#9 29-09-2010 20:13:57

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Accéder aux champs dans add_view()

@ Rémy

Ok, je n'ai pas rêvé. En fait, dans le cas de contrib.auth.admin,
UserAdmin n'hérite pas son add_form de ModelAdmin mais le définit pour
une personnalisation de sa méthode get_form. C'est un ajout spécifique
et c'est un exemple effectivement instructif.

@ ark

Oui, c'est amplement possible. Maintenant tu peux redéfinir le form de
ton choix dérivé du ModelForm utilisé par défaut [1]. C'est assez
pratique d'une manière générale pour indiquer explicitement des
exceptions à partir d'un modèle bien clair, par exemple quand le
contexte implique de réduire les "choices"  d'un champ ou quand tu veux
effectuer un travail préalable sur une section du ModelForm original.

[1]
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#form-inheritance

Hors ligne

#10 29-09-2010 23:06:01

ark
Membre
Inscription : 29-09-2010
Messages : 8

Re : Accéder aux champs dans add_view()

Merci, je m'en suis *presque* sorti en utilisant form de ModelAdmin, la surcharge de mon champ fonctionne bien.
Par contre je tourne en rond depuis 2h pour arriver au bout de ce que je veux faire, et maintenant je pense c'est dû à des lacunes côté python..
Je veux modifier mon champ en fonction de http_referer qui se trouve dans la request, request que je n'ai pas dans la classe directement.
Je passe donc par la méthode get_form() pour modifier le form, mais le souci est pour envoyer la request à MyNewsForm, ce sera + clair en voyant :

def get_form(self, request, obj=None, **kwargs):
        m = MyNewsForm(http_referer=request.META.get('HTTP_REFERER'))
        self.form = m.__class__
        return super(NewsAdmin, self).get_form(request, obj, **kwargs)

Donc jusque là tout va bien, je récupère mon arg dans le __init__, tout fonctionne toujours bien, mais quand je veux lier la surcharge de mon champ en utilisant mon arg ça va plus, plus du tout.
J'ai essayé plusieurs choses pour modifier mon champ à partir de mon arg (dans le init, avec l'instance dans le get_form, ..) mais ça ne veut pas.
Donc déjà c'est peut-être (surement) pas la bonne façon de faire, et mes lacunes en python me font faire des bêtises, j'y ai pourtant cru à plusieurs reprises.. !@#

Merci

Dernière modification par ark (29-09-2010 23:09:58)

Hors ligne

#11 29-09-2010 23:46:11

David Thenon
Membre
Inscription : 11-08-2010
Messages : 156
Site Web

Re : Accéder aux champs dans add_view()

Je ne comprends pas tout,

> quand je veux lier la surcharge de mon champ en utilisant mon arg ça va
plus, plus du tout

Ton argument "http_referer" récupéré dans le __init__ de ton modelform, tu le
met en attribut de ton objet (self.http_referer par exemple), tu essayes de
l'utiliser dans la méthode qui définit ton champ et finalement il existe pas
dans l'instance de modelform ?

Cordialement,
THENON David.

Hors ligne

#12 29-09-2010 23:59:32

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Accéder aux champs dans add_view()

ark,

J'aurais opté pour l'approche ci-dessous, même si je ne l'ai pas testée.
Le but est de dissocier la classe d'une instance particulière.

# forms.py
def get_news_form(http_referer):
     class Klass(MyNewsForm):
         # Modifie selon http_referer,
         # Pas besoin de toucher à self.__init__
     return Klass

# admin.py
def get_form(self, request, obj=None, **kwargs):
     self.form =
forms.get_new_form((http_referer=request.META.get('HTTP_REFERER'))
     return super(News

Hors ligne

#13 30-09-2010 12:27:25

Sarsae
Membre
Inscription : 19-09-2010
Messages : 4

Re : Accéder aux champs dans add_view()

Je ne suis pas sûr de bien avoir compris la demande, mais si c'est bien de modifier la liste des choix que présente par défaut un champ de type foreignkey, cette solution devrait convenir :

Il faut surcharger la méthode formfield_for_foreignkey du ModelAdmin.

http://docs.djangoproject.com/en/dev/re … foreignkey

Hors ligne

#14 30-09-2010 16:50:02

ark
Membre
Inscription : 29-09-2010
Messages : 8

Re : Accéder aux champs dans add_view()

Merci pour vos réponses,

David : En fait je l'utilisais dans la classe directement, pour ca que je ne l'avais pas, dans l'instance je l'ai bien, mais le problème est que form attend une classe, je ne peux donc pas lui donner l'instance. Si je fais ma modif dans l'instance puis lui donne la classe, la modification n'est pas prise en compte, j'ai essayé plusieurs trucs du genre, dont comme ça (le initial en dur pour le test) :

class MyNewsForm(forms.ModelForm):
    
    class Meta:
        model = News

    CAT_CHOICES = (
        (_("audition"), _("Audition")),
        (_("clinic"), _("Clinic")),
        (_("meeting"), _("Meeting")),
        (_("stage"), _("Stage")),
        (_("autre"), _("Autre")),
        )

    category = forms.ChoiceField(choices=CAT_CHOICES, widget=forms.Select(attrs={'disabled':'disabled'}))

    def change_cat(self,http_referer):
        print http_referer
        self.category = forms.ChoiceField(choices=self.CAT_CHOICES, initial='clinic', widget=forms.Select(attrs={'disabled':'disabled'}))


class NewsAdmin(admin.ModelAdmin):
    fields = ['title', 'summary', 'publication_date', 'author', 'category']
    formfield_overrides = {
        models.TextField: {'widget': TinyMCE(attrs={'cols': 80, 'rows': 15})}
        }

    def get_form(self, request, obj=None, **kwargs):
        m = MyNewsForm()
        m.change_cat(http_referer=request.META.get('HTTP_REFERER'))
        self.form = m.__class__
        return super(NewsAdmin, self).get_form(request, obj, **kwargs)

Il faut peut-être spécifier quelque chose à l'instance pour que ça sauvegarde, mais je n'ai pas trouvé.
J'ai aussi essayé en modifiant directement la propriété par l'instance, mais elle dit que category n'existe pas..

werefr0g : J'y ai bien cru avec cette méthode très maline smile mais le http_referer n'est utilisable que dans la méthode, dans la classe qui se trouve dans la méthode, il n'existe plus, sauf si j'ai raté quelque chose..

Sarsae : En fait la classe que je veux modifier est une clé étrangère de plusieurs autres classes, il faudrait donc que j'utilise cette méthode dans toutes mes autres classes, mais mon problème d'utiliser la request resterait le même, et ça dupliquerait du code pour rien, mais merci, bon à connaître cette méthode smile

Hors ligne

#15 30-09-2010 17:54:46

David Thenon
Membre
Inscription : 11-08-2010
Messages : 156
Site Web

Re : Accéder aux champs dans add_view()

Et donc tu a testé la technique de http://forum.django-fr.org/viewtopic.php?pid=2018#p2018 pour pouvoir passer ta variable et l'utiliser en attribut de l'objet (self.http_referer) dans ses méthodes ?

Hors ligne

#16 30-09-2010 18:47:52

Sarsae
Membre
Inscription : 19-09-2010
Messages : 4

Re : Accéder aux champs dans add_view()

ark a écrit :

Sarsae : En fait la classe que je veux modifier est une clé étrangère de plusieurs autres classes, il faudrait donc que j'utilise cette méthode dans toutes mes autres classes, mais mon problème d'utiliser la request resterait le même, et ça dupliquerait du code pour rien, mais merci, bon à connaître cette méthode smile

Le request est passé en paramètre de la méthode que je te donne, d'autre part, plutôt que de dupliquer le code, tu factorises en définissant une méthode que tu appelles dans toutes tes classes.

Dans tout les cas, si cette clef est utilisé dans plusieurs classes, il faudrait bien que tu "dupliques" soit du code, soit un forumlaire, mais il faudra bien dupliquer quelque chose.

Ou alors, j'ai pas bien compris et c'est dans la classe fille que tu veux filtrer, dans ce cas tu peux utiliser la surcharge de queryset dans la classe fille :

http://docs.djangoproject.com/en/dev/re … n.queryset

Mais ce qui serait bien c'est que nous explique clairement ce que tu veux faire ^^ (peut être que j'ai la "compregnure" difficile aussi ^^)

Dernière modification par Sarsae (30-09-2010 18:55:08)

Hors ligne

#17 30-09-2010 18:52:10

ark
Membre
Inscription : 29-09-2010
Messages : 8

Re : Accéder aux champs dans add_view()

Non j'avais raté ça effectivement, mais quand je modifie l'init comme tu dis, j'obtiens cette erreur quand je donne la classe au self.form dans le get_form():
Exception Value:    __init__() takes at least 2 non-keyword arguments (1 given)
Exception Location:    /usr/lib/pymodules/python2.6/django/contrib/admin/options.py in add_view, line 813

Mais de toute façon je devrai utiliser une méthode pour m'en servir, et donc créer une instance, ce qui ramène au précédent problème, il garde pas ce qui fait dans l'instance lorsque je lui donne la classe.

Hors ligne

#18 30-09-2010 19:09:47

ark
Membre
Inscription : 29-09-2010
Messages : 8

Re : Accéder aux champs dans add_view()

Sarsae a écrit :

Le request est passé en paramètre de la méthode que je te donne, d'autre part, plutôt que de dupliquer le code, tu factorises en définissant une méthode que tu appelles dans toutes tes classes.

Dans tout les cas, si cette clef est utilisé dans plusieurs classes, il faudrait bien que tu "dupliques" soit du code, soit un forumlaire, mais il faudra bien dupliquer quelque chose.

Ou alors, j'ai pas bien compris et c'est dans la classe fille que tu veux filtrer, dans ce cas tu peux utiliser la surcharge de queryset dans la classe fille :

http://docs.djangoproject.com/en/dev/re … n.queryset

Mais ce qui serait bien c'est que nous explique clairement ce que tu veux faire ^^ (peut être que j'ai la "compregnure" difficile aussi ^^)

Au temps pour moi pour le request, désolé.
Je sais pas pour ta compregnure, mais j'ai l'explicature difficile.
En fait c'est un système de news avec des catégories, où chaque catégorie est représentée par une classe car elles n'ont pas les même attributs.
Chacune de ces classes à une clé étrangère sur une classe principale News, qui a entre autre un attribut liste de choix avec les catégories en string.
il est donc possible soit de créer une news en passant par une classe catégorie, soit une news + simple en passant par la classe news et en mettant l'attribut choice sur 'autre'.
Pour le 1er cas, quand on crée cette news par l'admin, il y a donc le champ news en clé étrangère, qui ouvre une popup pour créer une nouvelle news. C'est dans cette popup que je veux forcer la liste de choix à se mettre sur la bonne catégorie en fonction du http_referer qui me dit le type de  news que c'est.

J'espère que c'est clair, mais au final j'aurais peut-être dû ne pas afficher du tout ce champ et forcer son enregistrement dans le save_model()?, mais je préférais  laisser une trace dans la popup news pour celui qui va les rentrer.

Merci..

Hors ligne

#19 01-10-2010 01:49:32

Sarsae
Membre
Inscription : 19-09-2010
Messages : 4

Re : Accéder aux champs dans add_view()

Si j'ai bien compris, à partir de la catégorie, tu veux pouvoir créer une news, avec comme valeur par défaut la catégorie ou tu étais au départ.

Mais que comptes tu faire quand à la base on créée une catégorie, que l'on ne renseigne rien et que l'on va direct en création de news ?

D'autre part dans ton raisonnement, vu que la news et un éléments enfant de la catégorie, cela signifie qu'une catégorie ne peut avoir qu'une seul news rattaché !

Habituellement ce sont les news qui ont une (ou plusieurs) clef étrangère vers la catégorie pas le contraire.

Dernière modification par Sarsae (01-10-2010 01:50:31)

Hors ligne

#20 01-10-2010 10:48:59

ark
Membre
Inscription : 29-09-2010
Messages : 8

Re : Accéder aux champs dans add_view()

Hmm oui une catégorie est rattachée à une seule news, mais une catégorie est aussi une news en elle-même, j'ai dû mal expliquer quelque part. Enfin ce système marche bien, beaucoup de news ont déjà été rentrées.
Bref bref, c'est pas grave, je m'en suis sorti autrement, je voulais me servir du save_model() de News mais forcement le http_referer dont j'avais besoin n'était plus bon vu que le save est une autre requête sur la meme form, et donc http_referer vaut cette form..*maudit*
Donc au final je n'affiche pas le champ catégory dans news, et je set sa valeur dans chaque save_model() de mes classes catégories en passant par obj.news.category, et c'est peut-être mieux au final.

Voilà, j'arrête de vous embêter et merci pour votre aide roll

Enfin si quelqu'un arrive quand même à passer un arg à la form dans le ModelAdmin, je serai pas contre de savoir, mais je m'y suis sûrement mal pris.

Hors ligne

Pied de page des forums