2012-06-25 21 views
5

Otrzymuję błąd "_reverse_with_prefix() argument po * musi być sekwencją, nie int", gdy próbuję odwrócić. Poprzednio zakodowałem parametr w widoku, ale próbuję uczynić go dynamicznym. Jakakolwiek rada?Jak poprawnie wykonać HttpResponseRedirect z odwróceniem?

Widok:

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

Zobacz także https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#redirect skrótu przekierowanie – super9

Odpowiedz

17

Sprawdź args=(p.id) wewnątrz reverse(), to musi być args=(p.id,). Pierwsza forma jest traktowana jako liczba całkowita zamiast sekwencji.

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

również wykorzystać 'reserve.views.view_reviews' zamiast jedynie 'view_reviews', a więc:

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

Sprawdź the doc of reverse

+0

Miałem poprzednio. Kiedy zmienię go z powrotem na args = (p.id), pojawia się błąd: Odwróć dla "view_reviews" z argumentami "(1)" i nie znaleziono argumentów słów kluczowych "{}". – sharataka

+0

@Sharataka sprawdź aktualizację, możesz również użyć [nazwy wzorca url] (https://docs.djangoproject.com/en/dev/topics/http/urls/#id2) – okm

1

Ponieważ wzór przypisuje dopasowanie do zmiennej, jest uważany za argument słowa kluczowego, więc powinieneś dostosować wywołanie do odwrócenia.

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

+0

Wprowadziłem tę zmianę i otrzymałem błąd "NoReverseMatch at/products/1/add_review /: Reverse dla 'view_reviews' z argumentami '()' i argumentów słów kluczowych '{' product_id ': 1}' nie znaleziono. Jest to dziwne, ponieważ kiedy używam wersji zakodowanej to id produktu o wartości 1. Ponadto nie jestem pewien, dlaczego błąd dotyczy "add_review" ... czy nie powinien on przekierowywać do view_reviews? – sharataka

+0

To nie ma znaczenia. – okm

0

to dlatego, że args trzeba krotki, ale kiedy używasz args = (p.id), faktycznie, pyton pomyśli jest liczbą całkowitą p.id, można spojrzeć kod źródłowy django 1.6, wykonaj:

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

wygląd tej iri_to_uri (resolver._reverse_with_prefix (widok, prefiks, * args, ** kwargs)), to użycie * args, dlatego należy zapewnić args jest sekwencją,

zgodnie z rozporządzeniami docs, tuple z jednym elementem powinny dodać przecinek do stworzenia, ty kod powinien być thi s:

return HttpResponseRedirect(reverse('view_reviews', args=(p.id,))) 
Powiązane problemy