2012-06-25 19 views
5

Me aparece un error "_reverse_with_prefix() argument after * debe ser una secuencia, no int" cuando intento revertir. Anteriormente codifiqué el parámetro en la vista, pero trato de hacerlo dinámico. ¿Algún consejo?¿Cómo hacer correctamente HttpResponseRedirect con reverse?

Vista:

def add_review(request, product_id): 
    p = get_object_or_404(Product, pk=product_id) 
    if request.method == 'POST': 
     form = ReviewForm(request.POST) 
     if form.is_valid(): 
      form.save() 
      #HARDCODED: return HttpResponseRedirect('/products/1/reviews/') 
      return HttpResponseRedirect(reverse('view_reviews', args=(p.id))) 
    else: 
     form = ReviewForm() 
    variables = RequestContext(request, {'form': form}) 
    return render_to_response('reserve/templates/create_review.html', variables)   


def view_reviews(request, product_id): 
    product = get_object_or_404(Product, pk=product_id) 
    reviews = Review.objects.filter(product_id=product_id) 
    return render_to_response('reserve/templates/view_reviews.html', {'product':product, 'reviews':reviews}, 
    context_instance=RequestContext(request)) 


urlpatterns = patterns('reserve.views', 
    url(r'^clubs/$', 'index'), 
    url(r'^products/(?P<product_id>\d+)/reviews/$', 'view_reviews'), 
    url(r'^products/(?P<product_id>\d+)/add_review/$', 'add_review'), 
    url(r'^admin/', include(admin.site.urls)), 
) 
+0

Véase también el acceso directo https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#redirect redirección – super9

Respuesta

17

Comprobar args=(p.id) dentro del reverse(), debe ser args=(p.id,). La primera forma se trata como un número entero en lugar de una secuencia.

Refs the doc y the tutorial:

A special problem is the construction of tuples containing 0 or 1 items: the syntax has some extra quirks to accommodate these. Empty tuples are constructed by an empty pair of parentheses; a tuple with one item is constructed by following a value with a comma (it is not sufficient to enclose a single value in parentheses).

También, el uso 'reserve.views.view_reviews' en lugar de simplemente 'view_reviews', por lo tanto:

reverse('reserve.views.view_reviews', args=(p.id,)) 

Comprobar the doc of reverse

+0

que solía tener que anteriormente. Cuando lo cambio a args = (p.id,) aparece el error: Inverso para 'view_reviews' con argumentos '(1,)' y argumentos de palabras clave '{}' no encontrados. – sharataka

+0

@sharataka revise la actualización, también puede usar [el nombre del patrón de la url] (https://docs.djangoproject.com/en/dev/topics/http/urls/#id2) – okm

1

Debido a que su patrón le asigna un partido a una variable, se considera un argumento clave, por lo que debe ajustar la llamada para revertir.

return HttpResponseRedirect(reverse('view_reviews', kwargs={'product_id':p.id})

+0

Realicé este cambio y obtuve el error "NoReverseMatch at/products/1/add_review /: Invertir para 'view_reviews' con argumentos '()' y argumentos de palabras clave '{' product_id ': 1}' no encontrados. Esto es extraño porque cuando uso la versión codificada, es un product_id con valor 1. Además, no estoy seguro de por qué el error es para "add_review" ... ¿no debería estar redirigiendo a view_reviews? – sharataka

+0

Esto no importa en realidad. – okm

0

eso es porque los argumentos necesitan tupla, pero cuando se utiliza los args = (p.id), en realidad, la pitón pensarán es p.id número entero, puede buscar el código fuente django 1.6 como siga:

def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None): 
if urlconf is None: 
    urlconf = get_urlconf() 
resolver = get_resolver(urlconf) 
args = args or [] 
kwargs = kwargs or {} 
if prefix is None: 
    prefix = get_script_prefix() 
if not isinstance(viewname, six.string_types): 
    view = viewname 
else: 
    parts = viewname.split(':') 
    parts.reverse() 
    view = parts[0] 
    path = parts[1:] 
    resolved_path = [] 
    ns_pattern = '' 
    while path: 
     ns = path.pop() 

     # Lookup the name to see if it could be an app identifier 
     try: 
      app_list = resolver.app_dict[ns] 
      # Yes! Path part matches an app in the current Resolver 
      if current_app and current_app in app_list: 
       # If we are reversing for a particular app, 
       # use that namespace 
       ns = current_app 
      elif ns not in app_list: 
       # The name isn't shared by one of the instances 
       # (i.e., the default) so just pick the first instance 
       # as the default. 
       ns = app_list[0] 
     except KeyError: 
      pass 

     try: 
      extra, resolver = resolver.namespace_dict[ns] 
      resolved_path.append(ns) 
      ns_pattern = ns_pattern + extra 
     except KeyError as key: 
      if resolved_path: 
       raise NoReverseMatch(
        "%s is not a registered namespace inside '%s'" % 
        (key, ':'.join(resolved_path))) 
      else: 
       raise NoReverseMatch("%s is not a registered namespace" % 
            key) 
    if ns_pattern: 
     resolver = get_ns_resolver(ns_pattern, resolver) 

return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)) 

mirada esta iri_to_uri (resolver._reverse_with_prefix (ver, prefijo, * args, ** kwargs)), se utilizan argumentos *, por lo que debe asegurarse de args es una secuencia,

según la documentos, la tupla con un elemento debería agregar la coma para crear, tu código debe ser thi s:

return HttpResponseRedirect(reverse('view_reviews', args=(p.id,)))