2011-02-14 10 views
30

Intento revertir una URL con nombre e incluir una cadena de consulta en ella. Básicamente, he modificado la función de inicio de sesión y deseo enviar ?next= en ella.Incluyendo una cadena de consulta en una llamada django.core.urlresolvers reverse()

Esto es lo que estoy haciendo ahora: reverse(name) + "?next=" + reverse(redirect)

Aquí es lo que me gusta hacer: reverse(name, kwargs = { 'next':reverse(redirect) })

Mi URL de la página de inicio de sesión (sólo como ejemplo) tiene el siguiente aspecto:

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

Entonces, ¿cómo modifico todo esto (o lo llamo) para incluir el siguiente sin tener que concatenarlo? Se siente como una solución dudosa en el mejor de los casos.

Respuesta

32

No se pueden capturar los parámetros GET en las configuraciones de URL, por lo que su método es el correcto.

Generalmente prefiero el formato de cadenas, pero es lo mismo.
"%s?next=%s" % (reverse(name), reverse(redirect))

http://docs.djangoproject.com/en/dev/topics/http/urls/#what-the-urlconf-searches-against

La URLconf búsquedas en contra de la URL solicitada, como una cadena normal de Python . Esto no incluye los parámetros POST GET o , ni el nombre de dominio.

7

Creo que es mejor ajustar el método inverso de Django para exponer esta API. Aquí hay un código simple de hacerlo:

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) 

poner este código en alguna utilidad o aplicación común que sólo depende de Django, a continuación, en lugar de importar django.core.urlresolvers.reverse simplemente importar myproject.myutils.urlresolvers.reverse

20

acabo de hacer mi propia función de utilidad como la que se le preguntó en la pregunta:

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 
4

yo estaba preocupado con la misma pregunta y encontramos este link. Aparentemente, su solución no está mal diseñada en absoluto. De acuerdo con la discusión del ticket, Django no proporcionará esta funcionalidad.

Puede usar urlobject o furl.

De la otra manera, es utilizar su propia función para hacer esto, de una manera mucho más limpia. Aquí está la indicada en la discusión

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 

En el caso de la pregunta, que puede ser utilizado de la siguiente manera

from [myfunctions] import reverse 
... 
reverse('login', get={next: reverse(redirect)}) 
1

Para mantener la consulta opcional, se puede envolver la función inversa de Django con su propia función que también maneja la consulta, lo que permite otro manejo adecuado de la función inversa.

Creación de una solicitud apropiada - Tenga en cuenta que la query_kwargs es opcional, por lo que no tiene que enviar

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

En utils.py archivo (basado en docs) para (1.11 y hasta?)

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

En las 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'), 

Y al acceder a la consulta

#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> 
Cuestiones relacionadas