2010-07-09 5 views
54

Dans ma fonction de vue je veux appeler une autre vue et transmettre des données à ce:Django redirect retour() avec des paramètres

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

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

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

On dirait que je dois fournir « une-nom_vue » argument, mais est-ce que le nom de la fonction de vue, ou le nom de l'url ? Je voudrais donc rendre semblable à la façon dont il est fait dans django-enregistrement, 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, je peux appeler la fonction directement ma vue ou dois-je fournir une URL pour cela? Et quoi de plus important, comment mon appel de funciotn (et une url si nécessaire) devrait ressembler? Le backend et clean_data sont simplement passés dans cette vue pour un usage ultérieur. Je l'ai essayé, mais il est incorrect:

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

Outre ceci:

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 l'enregistrement django, 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): 

Répondre

52

Tout d'abord, votre définition d'URL n'accepte aucun paramètre. Si vous voulez que les paramètres soient transmis de l'URL à la vue, vous devez les définir dans le fichier urlconf. Deuxièmement, il n'est pas du tout clair ce que vous attendez du dictionnaire des données nettoyées. N'oubliez pas que vous ne pouvez pas rediriger vers un POST - ceci est une limitation de HTTP, pas Django - donc vos données nettoyées doivent soit être un paramètre d'URL (horrible) ou, légèrement mieux, une série de paramètres GET - donc l'URL serait sous la forme:

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

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

Ainsi, votre URLconf serait:

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

et la vue ressemblerait à ceci:

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

et l'inverse serait (après l'importation urllib):

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

Édité après commentaireComme vous l'avez fait, l'utilisation de la redirection et de l'inversion est telle que vous accédez à l'URL: elle renvoie un code Http qui redirige le navigateur vers la nouvelle URL et l'appelle.

Si vous voulez simplement appeler la vue depuis votre code, faites-le directement - pas besoin d'utiliser le reverse du tout.

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

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

et si je ne vais pas opérer sur clean_data dans cette vue, mais juste le transmettre pour un usage ultérieur? J'ai beaucoup de champs dans la dict_data, donc je voudrais éviter de les passer comme une chaîne de caractères :) – muntu

+0

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

+0

cette deuxième vue stockera uniquement ces données envoyées pour un usage ultérieur. Mais êtes-vous sûr de devoir fournir l'URL pour cela? De docs il semble que je ne fais que l'appel directement à la vue. Aussi j'espérais simplement envoyer un dictionnaire avec le backend et les données dans redirect() (comme cela est fait dans django-registration) puis dans l'url (comme cette fonction dict in register), mais d'après ce que je vois c'est impossible? – muntu

29

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) 
    # ...