Question

J'ai un rapport Web qui utilise un formulaire Django (nouveaux formulaires) pour les champs qui contrôlent la requête utilisée pour générer le rapport (date de début, date de fin, ...). Le problème que je rencontre est que la page doit fonctionner avec les valeurs initiales du formulaire (non lié), mais je ne peux pas accéder au champ cleaner_data à moins d'appeler is_valid (). Mais is_valid () échoue toujours sur les formulaires non liés.

Il semble que les formulaires de Django ont été conçus avec le cas d'utilisation de l'édition de données, de sorte qu'un formulaire non lié n'est plus vraiment utile si vous affichez du code HTML.

Par exemple, si j'ai:

if request.method == 'GET':
    form = MyForm()
else:
    form = MyForm(request.method.POST)

if form.is_valid():
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

is_valid () échouera s'il s'agit d'un GET (puisqu'il n'est pas lié) et si je le fais:

if request.method == 'GET':
    form = MyForm()
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
else:
    form = MyForm(request.method.POST)
    if form.is_valid():
       do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

le premier appel à do_query déclenche des exceptions sur form.cleaned_data, ce qui n’est pas un champ valide car is_valid () n’a pas été appelé. Il semble que je doive faire quelque chose comme:

if request.method == 'GET':
    form = MyForm()
    do_query(form['start_date'].field.initial, form['end_date'].field.initial)
else:
    form = MyForm(request.method.POST)
    if form.is_valid():
       do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

En d'autres termes, il n'existe pas d'interface commune permettant de récupérer les valeurs du formulaire entre un formulaire lié et un formulaire non lié.

Quelqu'un voit-il une méthode plus propre pour le faire?

Était-ce utile?

La solution

Si vous ajoutez cette méthode à votre classe de formulaire:

def get_cleaned_or_initial(self, fieldname):
        if hasattr(self, 'cleaned_data'):
            return self.cleaned_data.get(fieldname)
        else:
            return self[fieldname].field.initial

vous pouvez alors réécrire votre code comme suit:

if request.method == 'GET':
    form = MyForm()
else:
    form = MyForm(request.method.POST)
    form.is_valid()

do_query(form.get_cleaned_or_initial('start_date'), form.get_cleaned_or_initial('end_date'))

Autres conseils

Unbound signifie qu'aucune donnée n'est associée au formulaire (initiale ou fournie ultérieurement), de sorte que la validation peut échouer. Comme indiqué dans d'autres réponses (et dans votre propre conclusion), vous devez fournir les valeurs initiales et rechercher les données liées et les valeurs initiales.

Le cas d'utilisation des formulaires est la validation des traitements et , vous devez donc disposer de certaines données à valider avant d'accéder à données_nettoyées .

Vous pouvez transmettre un dictionnaire de valeurs initiales à votre formulaire:

if request.method == "GET":
    # calculate my_start_date and my_end_date here...
    form = MyForm( { 'start_date': my_start_date, 'end_date': my_end_date} )
...

Voir la documentation officielle de l'API sur les formulaires , où ils présentent ceci.

modifier : sur la base des réponses d'autres utilisateurs, il s'agit peut-être de la solution la plus propre:

if request.method == "GET":
    form = MyForm()
    form['start_date'] = form['start_date'].field.initial
    form['end_date'] = form['end_date'].field.initial
else:
    form = MyForm(request.method.POST)
if form.is_valid():
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])

Je n'ai pas essayé cela cependant; quelqu'un peut-il confirmer que cela fonctionne? Je pense que cela vaut mieux que de créer une nouvelle méthode, car cette approche n’exige pas qu’un autre code (éventuellement non écrit par vous) connaisse votre nouvel accesseur 'magique'.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top