2012-06-25 35 views
5

Tôi gặp lỗi "đối số _reverse_with_prefix() sau * phải là một chuỗi, không phải int" khi tôi cố đảo ngược. Trước đây tôi đã mã hóa cứng tham số trong chế độ xem nhưng tôi đang cố gắng làm cho thông số động. Lời khuyên nào?Làm thế nào để thực hiện đúng HttpResponseRedirect ngược lại?

Xem:

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

Xem thêm chuyển hướng shortcut https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#redirect – super9

Trả lời

17

Kiểm tra args=(p.id) bên trong reverse(), nó phải là args=(p.id,). Biểu mẫu đầu tiên được coi là số nguyên thay vì một chuỗi.

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

Ngoài ra, sử dụng 'reserve.views.view_reviews' thay vì chỉ đơn thuần 'view_reviews', như sau:

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

Kiểm tra the doc of reverse

+0

Tôi đã từng có trước đó. Khi tôi thay đổi nó trở lại args = (p.id,) tôi nhận được lỗi: Đảo ngược 'view_reviews' với đối số '(1,)' và đối số từ khóa '{}' không tìm thấy. – sharataka

+0

@sharataka kiểm tra cập nhật, bạn cũng có thể sử dụng [tên mẫu url] (https://docs.djangoproject.com/en/dev/topics/http/urls/#id2) – okm

1

Kể từ khi mô hình của bạn gán một trận đấu cho một biến, nó được coi là một đối số từ khóa, vì vậy bạn nên điều chỉnh cuộc gọi để đảo ngược.

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

+0

Tôi đã thực hiện thay đổi này và tôi nhận được lỗi "NoReverseMatch tại/products/1/add_review /: Đảo ngược cho 'view_reviews' với đối số '()' và đối số từ khóa '{' product_id ': 1}' không tìm thấy. Điều này thật lạ vì khi tôi sử dụng phiên bản hardcoded, ở đó là một product_id với giá trị 1. Ngoài ra, tôi không chắc chắn tại sao lỗi là cho "add_review" ... không nên nó được chuyển hướng đến view_reviews? – sharataka

+0

Điều này không quan trọng thực sự. – okm

0

đó là bởi vì các args cần tuple, nhưng khi bạn sử dụng args = (p.id), trên thực tế, những trăn sẽ nghĩ là số nguyên p.id, bạn có thể tìm kiếm mã nguồn django 1.6 như theo:

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

nhìn iri_to_uri này (resolver._reverse_with_prefix (xem, tiền tố, * args, ** kwargs)), nó sử dụng * args, vì vậy bạn nên đảm bảo args là một chuỗi,

theo các tài liệu, tuple với một mục nên thêm dấu phẩy để tạo, bạn nên mã s:

return HttpResponseRedirect(reverse('view_reviews', args=(p.id,))) 
Các vấn đề liên quan