Django return redirect () với các tham số


81

Trong chức năng xem của tôi, tôi muốn gọi một chế độ xem khác và chuyển dữ liệu vào nó:

return redirect('some-view-name', backend, form.cleaned_data)

, trong đó backend là đối tượng register.backends và form.cleaned_data là một lệnh của dữ liệu biểu mẫu (nhưng cả hai đều phải được gửi dưới dạng * args hoặc ** kwargs để tránh tăng Don't mix *args and **kwargs in call to reverse()!lỗi). Từ những gì tôi tìm thấy trong tài liệu:

def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

Có vẻ như tôi cần cung cấp đối số 'some-view-name', nhưng nó chỉ là tên của chức năng xem hay tên của url? Vì vậy, tôi muốn làm cho nó tương tự như cách nó được thực hiện trong đăng ký django, trong đó:

to, args, kwargs = backend.post_registration_redirect(request, new_user)
return redirect(to, *args, **kwargs)

def post_registration_redirect(self, request, user):
    return ('registration_complete', (), {})

Được rồi, bây giờ tôi có thể gọi trực tiếp chức năng xem của mình hay tôi cần cung cấp url cho nó? Và điều quan trọng hơn, lệnh gọi funciotn của tôi (và một url nếu cần) sẽ trông như thế nào? Cả backend và clean_data đều được chuyển qua chế độ xem này để sử dụng sau này. Tôi đã thử điều này, nhưng nó không đúng:

url(r'^link/$', some-view-name)   
def some-view-name(request, *args):

Cũng như điều này:

return redirect('some_url', backend=backend, dataform.cleaned_data) 
url(r'^link/$', some-view-name)    
def some-view-name(request, backend, data):

vẫn là NoReverseMatch. Nhưng trong đăng ký django, tôi đã thấy một cái gì đó như thế này:

url(r'^register/$',register,{'backend': 'registration.backends.default.DefaultBackend'}, name='registration_register'),

def register(request, backend, success_url=None, form_class=None,
             disallowed_url='registration_disallowed',
             template_name='user/login_logout_register/registration_form.html',
             extra_context=None):

Câu trả lời:


66

Thứ nhất, định nghĩa URL của bạn không chấp nhận bất kỳ tham số nào. Nếu bạn muốn các tham số được chuyển từ URL vào dạng xem, bạn cần xác định chúng trong urlconf.

Thứ hai, hoàn toàn không rõ ràng những gì bạn mong đợi sẽ xảy ra với từ điển clean_data. Đừng quên rằng bạn không thể chuyển hướng đến POST - đây là một hạn chế của HTTP, không phải Django - vì vậy, dữ liệu clean_data của bạn cần phải là một tham số URL (khủng khiếp) hoặc tốt hơn một chút, một loạt các tham số GET - vì vậy URL sẽ có dạng:

/link/mybackend/?field1=value1&field2=value2&field3=value3

và như thế. Trong trường hợp này, field1, field2 và field3 không được bao gồm trong định nghĩa URLconf - chúng có sẵn trong chế độ xem qua request.GET.

Vì vậy, urlconf của bạn sẽ là:

url(r'^link/(?P<backend>\w+?)/$', my_function)

và chế độ xem sẽ giống như sau:

def my_function(request, backend):
   data = request.GET

và điều ngược lại sẽ là (sau khi nhập urllib):

return "%s?%s" % (redirect('my_function', args=(backend,)),
                  urllib.urlencode(form.cleaned_data))

Đã chỉnh sửa sau khi bình luận

Toàn bộ điểm của việc sử dụng chuyển hướng và đảo ngược, như bạn đã làm, là bạn đi đến URL - nó trả về mã Http khiến trình duyệt chuyển hướng đến URL mới và gọi nó.

Nếu bạn chỉ muốn gọi chế độ xem từ bên trong mã của mình, chỉ cần thực hiện trực tiếp - không cần sử dụng ngược lại.

Điều đó nói rằng, nếu tất cả những gì bạn muốn làm là lưu trữ dữ liệu, thì chỉ cần đặt nó vào phiên:

request.session['temp_data'] = form.cleaned_data

và nếu tôi không thao tác trên clean_data trong chế độ xem này mà chỉ chuyển nó để sử dụng sau? Tôi có rất nhiều lĩnh vực trong dict cleaned_data vì vậy tôi muốn tránh đi qua chúng như là một chuỗi get :)
muntu

Tôi không hiểu nhận xét này. Vui lòng giải thích chi tiết hơn, cập nhật câu hỏi của bạn nếu cần.
Daniel Roseman,

chế độ xem thứ hai này sẽ chỉ lưu trữ dữ liệu đã gửi này để sử dụng thêm. Nhưng bạn có chắc tôi cần cung cấp url cho nó không? Từ tài liệu, có vẻ như tôi đang gọi trực tiếp chế độ xem. Ngoài ra, tôi đã hy vọng chỉ gửi một từ điển với phụ trợ và dữ liệu trong redirect () (như nó được thực hiện trong đăng ký django) và sau đó trong url (như điều này trong hàm đăng ký), nhưng tôi thấy điều đó là không thể?
muntu

vâng vâng vâng đó là nó !! Tôi đã lãng phí quá nhiều thời gian cho nó mà hoàn toàn quên mất các phiên: / chết tiệt, cảm ơn !!
muntu

1
điểm tốt về việc chỉ gọi hàm nếu một hàm không cần URL.
maxbellec

58

urls.py:

#...    
url(r'element/update/(?P<pk>\d+)/$', 'element.views.element_update', name='element_update'),

views.py:

from django.shortcuts import redirect
from .models import Element


def element_info(request):
    # ...
    element = Element.object.get(pk=1)
    return redirect('element_update', pk=element.id)

def element_update(request, pk)
    # ...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.