web-dev-qa-db-fra.com

Inclusion d'une chaîne de requête dans un appel Django.core.urlresolvers reverse ()

J'essaie d'inverser une URL nommée et d'y inclure une chaîne de requête. En gros, j'ai modifié la fonction de connexion et je veux y envoyer ?next=.

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 (à titre d'exemple) ressemble à ceci:

url(r'^login/', custom_login, name = 'login'),

Alors, comment puis-je modifier tout cela (ou l'appeler) pour inclure le suivant sans avoir à le concaténer? C'est au mieux une solution douteuse.

36
Brian Hicks

Vous ne pouvez pas capturer les paramètres GET dans l'URL confs, votre méthode est donc 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

URLconf recherche l'URL demandée Sous forme de chaîne Python Normale. Cela n'inclut pas les paramètres GET ou POST>, ni le nom de domaine.

42
Yuji 'Tomita' Tomita

Je viens de créer ma propre fonction d’utilité, semblable à 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
22
Daniel Backman

Je pense qu'il vaut mieux 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 un utilitaire ou une application commune qui ne dépend que de Django. Au lieu d'importer Django.core.urlresolvers.reverse, importez simplement myproject.myutils.urlresolvers.reverse.

6
Alan Illing

J'ai été troublé par la même question et j'ai trouvé ce link . Apparemment, votre solution n'est pas mal conçue du tout. Selon la discussion sur le ticket, Django ne fournira pas cette fonctionnalité.

Vous pouvez utiliser urlobject ou furl .

L'autre façon, consiste à utiliser votre propre fonction pour le 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)})
6

Pour que la requête reste facultative, vous pouvez envelopper la fonction inverse de Django avec votre propre fonction qui gère également la requête, ce qui permet un traitement approprié de la fonction inverse.

Création d'une demande correcte - Notez que le query_kwargs est facultatif, vous n'avez donc 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 le fichier utils.py (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 urls 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 accéder à 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>
0
chris Frisina