Y compris une requête dans un appel django.core.urlresolvers reverse ()
Question
J'essaie d'inverser une URL nommée et d'inclure une requête dedans. Fondamentalement, j'ai modifié la fonction de connexion, et je veux envoyer ?next=
en elle.
Voici ce que je fais maintenant: reverse(name) + "?next=" + reverse(redirect)
Voici ce que j'aimerais faire: reverse(name, kwargs = { 'next':reverse(redirect) } )
Mon URL pour la page de connexion (comme un exemple) ressemble à ceci:
url(r'^login/', custom_login, name = 'login'),
Alors, comment modifier tout cela (ou l'appeler) pour inclure le suivant sans avoir à le concaténer? Cela ressemble au mieux à une solution incertaine.
La solution
Vous ne pouvez pas capturer des paramètres dans les confs URL, donc votre méthode est correcte.
Je préfère généralement le formatage des chaînes, mais c'est la même chose.
"%s?next=%s" % (reverse(name), reverse(redirect))
http://docs.djangoproject.com/en/dev/topics/http/urls/#what-the-urlconf-searches-against
L'URLCONF recherche par rapport à l'URL demandée, en tant que chaîne Python normale. Cela n'inclut pas les paramètres Get ou Post, ni le nom de domaine.
Autres conseils
Je viens de faire ma propre fonction d'utilité comme celle posée dans la question:
from django.utils.http import urlencode
def my_reverse(viewname, kwargs=None, query_kwargs=None):
"""
Custom reverse to add a query string after the url
Example usage:
url = my_reverse('my_test_url', kwargs={'pk': object.id}, query_kwargs={'next': reverse('home')})
"""
url = reverse(viewname, kwargs=kwargs)
if query_kwargs:
return u'%s?%s' % (url, urlencode(query_kwargs))
return url
Je pense qu'il est préférable d'envelopper la méthode inverse de Django pour exposer cette API. Voici un code simple pour le faire:
from django.core.urlresolvers import reverse as django_reverse
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
"""
Wrapper of django.core.urlresolvers.reverse that attaches arguments in kwargs as query string parameters
"""
if kwargs:
return '%s?%s' % (django_reverse(viewname, urlconf, args, None, prefix, current_app), \
'&'.join(['%s=%s' % (k,v) for k,v in kwargs.items()]))
else:
return django_reverse(viewname, urlconf, args, kwargs, prefix, current_app)
Mettez ce code dans une utilité ou une application commune qui ne dépend que de Django, alors au lieu d'importer django.core.urlresolvers.reverse importe simplement myproject.myutils.urlresolvers.reverse
J'étais troublé par la même question et j'ai trouvé cela lien. Apparemment, votre solution n'est pas du tout conçue. Selon la discussion sur les billets, Django ne fournira pas cette fonctionnalité.
Vous pourriez utiliser Urlobject ou rouler.
L'autre moyen est d'utiliser votre propre fonction pour ce faire, d'une manière beaucoup plus propre. Voici celui indiqué dans la discussion
from django.utils.http import urlencode
from django.core.urlresolvers import reverse as original_reverse
def reverse(*args, **kwargs):
get = kwargs.pop('get', {})
url = original_reverse(*args, **kwargs)
if get:
url += '?' + urlencode(get)
return url
Dans le cas de la question, il peut être utilisé de la manière suivante
from [myfunctions] import reverse
...
reverse('login', get={next: reverse(redirect)})
Pour garder la requête en option, vous pouvez envelopper la fonction inverse de Django avec votre propre fonction qui gère également la requête, permettant une autre gestion appropriée de la fonction inverse.
Création d'une demande appropriée - Notez que le query_kwargs
est facultatif, donc vous n'avez pas à l'envoyer
# from a views in views.py
def sendingView(request, truckID, fleetSlug):
#in the GET or POST
return HttpResponseRedirect(reverse('subAppName:urlViewName',
kwargs={'anyPassedKawrgs':goHere,…},
query_kwargs={'queries': goHere}
))
# from a template in specificTemplate.html
<a class="nav-link" href="{% url 'subAppName:urlViewName' kwarg1=kwarg1 kwarg2=kwarg2 … query_kwargs={'dict':here} %}">Link</a>
#from a model in models.py
class Truck(models.Model):
name = models.CharField(…)
def get_absolute_wi_url(self):
return reverse('subAppName:urlViewName', kwargs={'kwarg1':kwarg1,'kwarg2':kwarg2})
Dans utils.py
fichier (basé sur docs) pour (1.11 et plus?)
-myMainApp
-apps
-static
...
-utils
-__init__.py
-utils.py
from django.core.urlresolvers import reverse as django_reverse
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, query_kwargs=None):
"""
Wrapper of django.core.urlresolvers.reverse that attaches arguments in kwargs as query string parameters
"""
if query_kwargs:
return '%s?%s' % (django_reverse(viewname, urlconf, args, kwargs, current_app), \
'&'.join(['%s=%s' % (k,v) for k,v in query_kwargs.items()]))
else:
return django_reverse(viewname, urlconf, args, kwargs, current_app)
Dans les URL conf. urls.py
app_name = 'subAppName'
urlpatterns = [
url(r'^(?P<kawrg1>[a-zA-Z0-9]+)/(?P<kawrg2>[a-zA-Z0-9]+)/path/to/here/$', views.urlViewFunctionName, name='urlViewName'),
Et avoir accès à la requête
#in a view
def urlViewFunctionName(request, kwarg1, kwarg2):
if request.GET.get('submittedData'):
submittedQuery = request.GET.get('submittedData')
else:
submittedQuery = None
return render(request, 'trucks/weeklyInspectionSuccess.html', {
'truck': truck,
'submittedQuery': submittedQuery
})
#in a template
<div class="container">
Success for {{kwarg1}}
{{submittedQuery}}
</div>