Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Comment utiliser l'option can_order d'un formset?

+2 votes

Comment fonctionne le paramètre can_order pour les formset?
Je ne sais pas changer l'ordre, comment je dois faire?
J'ai beau lire et relire la doc et chercher sur les forums mais je ne trouve rien.
J'ai implémenté un inlineformset dynamique. Mes champs sont un select pointant sur une base de données regroupant des actes médicaux avec les tarifs. L'utilisateur doit donc sélectionner ses actes sans se soucier du tarif. Mon objectif est de trier du plus cher au moins cher pour y appliquer un coefficient.cela avant le save (). Je pensais que l'option can_order m'aiderait mais je ne sais pas comment changer la valeur. Si vous avez un exemple je suis preneur!

demandé 2-Jun-2015 par Victor (218 points)
edité 2-Jun-2015 par Nsukami_

2 Réponses

+1 vote

can_order tri les formulaires non les données de ces formulaires :

la doc en vf dit :
"La méthode formset _ factory() fournit deux paramètres facultatifs canorder et candelete pour faciliter le tri et la suppression de formulaires dans des formulaires groupés."

répondu 2-Jun-2015 par foxmask (2,892 points)

Je ne me suis pas fait comprendre peut être ou je n'emploie pas les bons termes. Il s'agit bien, si j'ai bien compris, de formulaire. Par ex le médecin accompli 3 actes. Dans le 1er formulaire il recherche l'acte puis clic pour ajouter un autre formulaire, sélectionne le suivant puis un dernier.
Je me retrouve avec 3 actes (form-0, form-1,form-2).
Je souhaite faire le tri de ces trois formulaire. Parmi l'acte sélectionné il y a le montant. Je cherche à faire une routine sur ce montant pour modifier la valeur de form-i-ORDER. Mais je ne sais pas acceder à form-i-ORDER! C'est possible?

Effectivement je n'avais pas compris s comme ça. Je creuse ;)

il semble que le nombre total de forms créés soit dispo via https://docs.djangoproject.com/fr/1.8/topics/forms/formsets/#total-form-count-and-initial-form-count
J'ai pas testé, mais cela dit je ferai une boucle sur les form contenus dans le formset pour les réordonner à ma sauce et enchainerai par form.save() pour chaque form et ne ferai pas de formset.save() puisque je suis pas en mesure de remettre les forms dans le formset - sans passer par une usine à gaz qui reinstancie les form dans le formset dans l'ordre des montants

Mon form-i-ORDER n'est pas incrémenté... j'ai None dedans.
Il n'est pas non plus de type integer, il est même sans type.
Est ce que c'est à moi de gérer l'incrément? Je pensais que si canorder = true il faisait ça seul! C'est vraiment pas clair l'exemple de la doc. Quelqu'un a déjà implémenté un inlineformset avec canorder à True?

J'ai un projet avec ça je vais lui rajouter a pour tester. Je te tiens au courant

alors de ce que j'ai observé, django nomme les champs en ajoutant le nom du formset
chez moi j'ai un formset ExaminationDetails, du coup les champs sont

id_examinationdetails_set-TOTAL_FORMS
id_examinationdetails_set-INITIAL_FORMS

id_examinationdetails_set-0-ORDER
id_examinationdetails_set-0-DELETE

dans mon formset j'ai 4 record existants ce qui fait que INITIAL_FORMS est à 4 et TOTAL_FORMS à 6 car j'ai mis dans la definition de mon inline_formset extra=2,
du coup j'ai des input de id_examinationdetails_set-0-ORDER à id_examinationdetails_set-5-ORDER

je n'ai pas cherché à manipuler les données, juste à produire un formulaire avec can_order=True en plus

pour être sûr que j'en laisse pas à coté, quand je dev, je fais ca :

{% for form in formset %}
{{ form.as_table }}
{% endfor %}

quand c'est ok je vire as_table et personnalise

J'espere que ca eclairera ta lanterne

Je fais pareil. J'ai bien mes IDxxxxccSET-i-ORDER mais il y a none dedans. Pas d'incrementation. Je galère...je vais creuser...je vais finir par trouver du pétrole. Merci pour ton aide.

Tu as None quand tu save ton form, ou lors du chargement du form avec des données ???

Sinon apres un test rapidos j'ai trouvé ORDER dans les cleanded_data du formset :)

if formset.is_valid():
    for cleaned_data in formset.cleaned_data:
        if len(cleaned_data) > 0: #ici j'ignore les inlineformset non remplis
            print (cleaned_data['ORDER'])
+1 vote

Merci à Foxmask ça m'a aiguillé.
En fait je pensais que canorder = True incrémentait automatiquement les forms... En fait je m'aperçois que c'est un peu ridicule. En fait soit on le gère manuellement dans la page html via un champ saisissable, soit evidement on le gère dans le code. Le canorder = True active simplement le champ 'ORDER' dans chaque form pour y avoir accès, c'est tout.
Je mets le code de ma petite sauce. Vu mon niveau, si vous avez des commentaires pour m'améliorer ou pour faire plus simple, je suis preneur.

# but: tri décroissant en fonction du tarif
    # constitution d'une liste des montants à trier.
    liste_mnt =[]
    for i in range(form.total_form_count()):
            liste_mnt.append(form[i].cleaned_data['force_mnt'])

    liste_mnt.sort()
    i=0
    # itération pour rechercher les montants de la liste trié et la correspondance dans les form
    #  et incrémenter ORDER en fonction du rang i de la liste dans l'ordre decroissant des montants.
    for i  in range(len(liste_mnt)):
        for j in range(form.total_form_count()):
            if  liste_mnt[i] == form[j].cleaned_data['force_mnt'] \
                    and form[j].cleaned_data['ORDER'] ==  None:
                form[j].cleaned_data['ORDER'] = len(liste_mnt) - i
répondu 5-Jun-2015 par Victor (218 points)
...