115 votes

Django retourne redirect() avec des paramètres

Dans ma fonction de vue, je veux appeler une autre vue et lui transmettre des données :

return redirect('some-view-name', backend, form.cleaned_data)

où backend est un objet registration.backends, et form.cleaned_data est un dict de données de formulaire (mais les deux doivent être envoyés en tant que *args ou **kwargs afin d'éviter de soulever des problèmes de type Don't mix *args and **kwargs in call to reverse()! erreur). D'après ce que j'ai trouvé dans la documentation :

def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

Il semble que je doive fournir l'argument 'some-view-name', mais est-ce juste le nom de la fonction de vue, ou le nom de l'url ? J'aimerais donc que cela soit similaire à ce qui est fait dans django-registration, où :

to, args, kwargs = backend.post_registration_redirect(request, new_user)
return redirect(to, *args, **kwargs)

def post_registration_redirect(self, request, user):
    return ('registration_complete', (), {})

Ok, maintenant, puis-je appeler directement ma fonction de vue ou dois-je lui fournir une url ? Et plus important encore, à quoi doit ressembler l'appel de ma fonction (et l'url si nécessaire) ? Le backend et les cleaned_data sont juste passés par cette vue pour une utilisation ultérieure. J'ai essayé cela, mais c'est incorrect :

url(r'^link/$', some-view-name)   
def some-view-name(request, *args):

En plus de cela :

return redirect('some_url', backend=backend, dataform.cleaned_data) 
url(r'^link/$', some-view-name)    
def some-view-name(request, backend, data):

encore NoReverseMatch . Mais dans django-registration, j'ai vu quelque chose comme ceci :

url(r'^register/$',register,{'backend': 'registration.backends.default.DefaultBackend'}, name='registration_register'),

def register(request, backend, success_url=None, form_class=None,
             disallowed_url='registration_disallowed',
             template_name='user/login_logout_register/registration_form.html',
             extra_context=None):

94voto

roach Points 91

Urls.py :

#...    
url(r'element/update/(?P<pk>\d+)/$', 'element.views.element_update', name='element_update'),

views.py :

from django.shortcuts import redirect
from .models import Element

def element_info(request):
    # ...
    element = Element.object.get(pk=1)
    return redirect('element_update', pk=element.id)

def element_update(request, pk)
    # ...

2 votes

Ces trucs/manières/éléments de connaissance profonde sont vraiment utiles. merci beaucoup.

82voto

Daniel Roseman Points 199743

Tout d'abord, votre définition d'URL n'accepte aucun paramètre. Si vous voulez que des paramètres soient transmis de l'URL à la vue, vous devez les définir dans l'urlconf.

Deuxièmement, ce que vous attendez du dictionnaire cleaned_data n'est pas du tout clair. N'oubliez pas que vous ne pouvez pas rediriger vers un POST - c'est une limitation de HTTP, pas de Django - donc vos cleaned_data doivent être un paramètre d'URL (horrible) ou, légèrement mieux, une série de paramètres GET - donc l'URL serait de la forme :

/link/mybackend/?field1=value1&field2=value2&field3=value3

et ainsi de suite. Dans ce cas, champ1, champ2 et champ3 sont no inclus dans la définition d'URLconf - ils sont disponibles dans la vue via request.GET .

Donc votre urlconf serait :

url(r'^link/(?P<backend>\w+?)/$', my_function)

et la vue ressemblerait à :

def my_function(request, backend):
   data = request.GET

et l'inverse serait (après avoir importé urllib ) :

return "%s?%s" % (redirect('my_function', args=(backend,)),
                  urllib.urlencode(form.cleaned_data))

Modifié après le commentaire

L'intérêt de l'utilisation de la redirection et de l'inversion, comme vous l'avez fait, est que vous allez à l'URL - il renvoie un code Http qui amène le navigateur à rediriger vers la nouvelle URL, et vous l'appelez.

Si vous voulez simplement appeler la vue à partir de votre code, faites-le directement - il n'est pas nécessaire d'utiliser reverse.

Cela dit, si tout ce que vous voulez faire est de stocker les données, il suffit de les mettre dans la session :

request.session['temp_data'] = form.cleaned_data

2 votes

Et si je ne vais pas opérer sur les données nettoyées dans cette vue, mais juste les passer pour une utilisation ultérieure ? J'ai beaucoup de champs dans le dictateur cleaned_data donc je voudrais éviter de les passer en tant que chaîne get :)

2 votes

Je ne comprends pas ce commentaire. Veuillez expliquer plus en détail, en mettant à jour votre question si nécessaire.

0 votes

Cette deuxième vue ne stockera que les données envoyées pour une utilisation ultérieure. Mais êtes-vous sûr que je dois fournir une url pour cela ? D'après la documentation, il semble que je n'ai qu'à appeler la vue directement. J'espérais également pouvoir envoyer un dictionnaire avec le backend et les données dans redirect() (comme cela est fait dans django-registration) et ensuite dans l'url (comme ce dict dans la fonction register), mais d'après ce que je vois, c'est impossible ?

11voto

yanqzhi Points 1

Je fais comme ceci dans django3

redirect_url = reverse('my_function', args=(backend,))
parameters = urlencode(form.cleaned_data)
return redirect(f'{redirect_url}?{parameters}')

2voto

Rafsan Points 36

Je suis nouveau dans le monde de Django. Dans un de mes projets, j'ai utilisé render au lieu de redirect pour envoyer des données. Cela a bien fonctionné. Mon code était comme ceci --->

  for key, value in request.POST.lists():
        print(key, value)
        if key.split('-')[-1] != 'csrfmiddlewaretoken':
            qu_id = key.split('-')[-1]
            get_answer = Answer.objects.filter(question_id=qu_id,
                                               correct_answer__option__contains=value[0])
            total_correct_answer = get_answer.count()
    context = {'score': total_correct_answer}
    return render(request, 'result.html', context)
context = {'questions': questions, 'total_correct_answer': total_correct_answer}
return render(request, 'test.html', context)

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