2012-06-25 9 views
5

Ricevo un errore "_reverse_with_prefix() argomento dopo * deve essere una sequenza, non int" quando provo a invertire. Ho precedentemente codificato il parametro nella vista, ma sto cercando di renderlo dinamico. Qualche consiglio?Come eseguire correttamente 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

vedere anche il reindirizzamento https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#redirect scorciatoia – super9

risposta

17

Controllare args=(p.id) all'interno del reverse(), deve essere args=(p.id,). La prima forma viene considerata come numero intero anziché come sequenza.

Refs the doc e 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).

Inoltre, utilizzare 'reserve.views.view_reviews' invece di limitarsi a 'view_reviews', in tal modo:

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

check the doc of reverse

+0

Ho usato per avere che in precedenza. Quando lo cambio a args = (p.id,) ottengo l'errore: Reverse per 'view_reviews' con argomenti '(1,)' e argomenti di parole chiave '{}' non trovati. – sharataka

+0

@sharataka controlla l'aggiornamento, puoi anche usare [il nome del pattern url] (https://docs.djangoproject.com/en/dev/topics/http/urls/#id2) – okm

1

Dal momento che il modello assegna una corrispondenza a una variabile, è considerato un argomento di parole chiave, quindi è necessario regolare la chiamata al contrario.

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

+0

Ho apportato questo cambiamento e ottengo il errore "NoReverseMatch at/products/1/add_review /: Reverse per 'view_reviews' con argomenti '()' e argomenti parola chiave '{' product_id ': 1}' non trovato.Questo è strano perché quando uso la versione hardcoded, ci è un product_id con valore 1. Inoltre, non sono sicuro del motivo per cui l'errore è per "add_review" ... non dovrebbe essere reindirizzamento per visualizzare_reviews? – sharataka

+0

Questo non importa in realtà. – okm

0

Questo perché l'args bisogno di tuple, ma quando si utilizzano i args = (p.id), in realtà, il pitone penserà è p.id intero, si può guardare il codice sorgente Django 1.6 come seguire:

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

aspetto questo iri_to_uri (resolver._reverse_with_prefix (vista, il prefisso, * args, ** kwargs)), esso uso args *, così si dovrebbe garantire args è una sequenza,

secondo la documenti, tupla con un elemento dovrebbe aggiungere la virgola per creare, il codice dovrebbe essere thi s:

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