2010-06-11 39 views
60

Khi xử lý yêu cầu POST trong tệp viewsango Django, đôi khi tôi cần phải chuyển hướng nó đến một url khác. Url này tôi đang chuyển hướng đến được xử lý bởi một hàm khác trong cùng một tệp Django views.py. Có cách nào để thực hiện việc này và duy trì dữ liệu POST gốc không?Django: Làm cách nào để chuyển hướng bài đăng và chuyển vào dữ liệu bài đăng

CẬP NHẬT: Giải thích thêm về lý do tôi muốn thực hiện việc này. Tôi có hai ứng dụng web (hãy gọi chúng là AppA và AppB) để chấp nhận dữ liệu được nhập vào trường văn bản của người dùng. Khi người dùng nhấp vào gửi, dữ liệu được xử lý và kết quả chi tiết được hiển thị. AppA và AppB mong đợi các loại dữ liệu khác nhau. Đôi khi người dùng nhầm lẫn đăng dữ liệu loại AppB lên AppA. Khi điều này xảy ra, tôi muốn chuyển hướng chúng đến AppB và hiển thị kết quả AppB hoặc ít nhất là nó có dữ liệu được nhập vào AppA.

Ngoài ra:

  • Các khách hàng muốn hai ứng dụng riêng biệt chứ không phải là kết hợp chúng vào chỉ là một.

  • Tôi không thể hiển thị mã vì nó thuộc về khách hàng.

CẬP NHẬT 2: Tôi đã quyết định rằng KISS là nguyên tắc tốt nhất ở đây. Tôi đã kết hợp hai ứng dụng thành một ứng dụng giúp mọi thứ trở nên đơn giản và mạnh mẽ hơn; Tôi sẽ có thể thuyết phục khách hàng đó là cách tốt nhất để đi. Cảm ơn vì tất cả những phản hồi tuyệt vời. Nếu tôi định duy trì hai ứng dụng như được mô tả thì tôi nghĩ các phiên sẽ là cách để làm điều này - nhờ Matthew J Morrison đã đề xuất điều đó. Nhờ Dzida như ý kiến ​​của ông đã cho tôi suy nghĩ về thiết kế và đơn giản hóa.

+0

bạn có thực sự cần phải gửi một chuyển hướng cho khách hàng, hoặc là một cái gì đó này có thể được thực hiện bằng cách chỉ gọi một hàm và chuyển tất cả dữ liệu đăng lên đó? –

+0

Tôi cần thay đổi url tại trình duyệt của khách hàng, vì vậy đây là cách duy nhất tôi có thể làm điều đó. – FunLovinCoder

+0

và bạn không thể làm tất cả việc xử lý với dữ liệu bài đăng đầu tiên, và sau đó chuyển hướng sau khi thực tế? –

Trả lời

45

Nếu bạn gặp phải sự cố như vậy, bạn có thể cần sửa đổi thiết kế của mình một chút.

Đây là hạn chế của HTTP mà dữ liệu POST không thể đi với chuyển hướng.

Bạn có thể mô tả những gì bạn đang cố gắng hoàn thành và có thể sau đó chúng ta có thể nghĩ về một số giải pháp gọn gàng.

Nếu bạn không muốn sử dụng phiên làm việc, Matthew đề xuất bạn có thể chuyển thông số POST trong GET tới trang mới (xem xét một số giới hạn như bảo mật và độ dài tối đa của các tham số GET trong chuỗi truy vấn).

CẬP NHẬT cập nhật của bạn :) Nghe có vẻ kỳ lạ với tôi rằng bạn có 2 ứng dụng web và các ứng dụng đó sử dụng một views.py (tôi có đúng không?). Dù sao, hãy xem xét chuyển dữ liệu của bạn từ POST trong GET đến chế độ xem thích hợp (trong trường hợp dữ liệu không nhạy cảm với khóa học).

+2

Tôi có thể thấy những gì anh ta đang cố gắng làm có thể hợp lệ nếu anh ta cố gắng xử lý đăng nhập hết hạn sẽ buộc người dùng đăng nhập sau khi gửi biểu mẫu ... trong trường hợp đó, anh ấy sẽ muốn giữ lại dữ liệu đã được gửi và không buộc người dùng phải nhập lại mọi thứ sau khi họ hoàn thành màn hình đăng nhập. –

+0

Không chắc chắn nếu tôi có điểm nhưng trong trường hợp này hoạt động đăng nhập có thể được thực hiện bằng cách xem đầu tiên với ít sửa đổi mã và không thực hiện chuyển hướng không cần thiết. Nó sẽ là tuyệt vời để đọc mã exisitng để làm cho lời khuyên chính xác hơn. – dzida

+0

Tôi đang nói nếu bạn gửi biểu mẫu và bạn chưa đăng nhập, bạn sẽ được chuyển hướng đến biểu mẫu đăng nhập ... trong trường hợp đó, bạn sẽ mất mọi thứ bạn đã gửi. Tôi đồng ý về việc có thể xem một số mã hiện có. –

40

Tôi nghĩ làm thế nào tôi có thể xử lý tình huống này sẽ là để lưu dữ liệu bài trong phiên, sau đó loại bỏ nó khi tôi không còn cần nó. Bằng cách đó, tôi có thể truy cập dữ liệu bài đăng gốc sau khi chuyển hướng ngay cả khi bài đăng đó đã biến mất.

Điều đó có hiệu quả với những gì bạn đang cố gắng làm không?

Đây là một mẫu mã của những gì tôi đang đề nghị: (ghi nhớ này là mã chưa được kiểm tra)

def some_view(request): 
    #do some stuff 
    request.session['_old_post'] = request.POST 
    return HttpResponseRedirect('next_view') 

def next_view(request): 
    old_post = request.session.get('_old_post') 
    #do some stuff using old_post 

Một điều khác cần lưu ý ... nếu bạn đang làm điều này và cũng có thể tải lên các tập tin, tôi sẽ không làm theo cách này.

+1

Tôi chưa bao giờ sử dụng phiên, nhưng tôi sẽ có một cái nhìn tại đó cảm ơn. – FunLovinCoder

+1

đây không phải là thực hành tốt nhất, nhưng vẫn giúp. Tôi đoán cho vấn đề này, chúng tôi sẽ không nhận được bất cứ điều gì đẹp hơn. –

+0

@GuilhermeDaviddaCosta tại sao bạn nói nó không phải là thực hành tốt nhất? Bạn có thể gợi ý cho chúng tôi không? –

0

Nếu bạn đang sử dụng chuyển hướng sau khi xử lý POST thành AppB, bạn có thể thực sự thoát khỏi bằng cách gọi phương thức AppB từ phương thức AppA.

Một thí dụ:

def is_appa_request(request): 
    ## do some magic. 
    return False or True 
is_appb_request = is_appa_request 

def AppA(request): 
    if is_appb_request(request): 
     return AppB(request) 
    ## Process AppA. 
    return HttpResponseRedirect('/appa/thank_you/') 

def AppB(request): 
    if is_appa_request(request): 
     return AppA(request) 
    ## Process AppB. 
    return HttpResponseRedirect('/appb/thank_you/') 

này nên mang lại một trải nghiệm trong suốt cho người dùng cuối, và khách hàng người thuê có thể bạn sẽ không bao giờ biết sự khác biệt.

Nếu bạn không chuyển hướng sau POST, bạn có lo lắng về dữ liệu trùng lặp do người dùng làm mới trang không?

+0

Nó sẽ là tuyệt vời nếu một giải pháp đơn giản như thế này làm việc. Tuy nhiên, tôi cần hiển thị kết quả chi tiết sau khi xử lý dữ liệu. Điều này đòi hỏi các phiên (như được đề xuất bởi Matthew J Morrison) phải không? – FunLovinCoder

+1

Bạn có thể thực hiện theo một trong ba cách. # 1, lưu trữ dữ liệu trong cơ sở dữ liệu và chuyển 'pk' của mục nhập mới khi bạn chuyển hướng. # 2, lưu trữ dữ liệu trong phần phụ trợ 'cache' và truyền lại khóa. # 3, lưu trữ nó trong phiên. Bất kỳ điều nào trong số này hoàn toàn bình thường đối với một ứng dụng web để làm, ngay cả khi nó là tạm thời. Nếu dữ liệu biểu mẫu là không tầm thường để phân tích cú pháp, nó cũng sẽ làm cho hệ thống nhanh hơn nếu đầu ra đã được lưu trữ. –

14

Bạn cần sử dụng HTTP 1.1 Temporary Redirect (307).

Thật không may, Django redirect()HTTPResponseRedirect (vĩnh viễn) trả về chỉ một 301 hoặc 302. Bạn phải thực hiện nó cho mình:

from django.http import HttpResponse, iri_to_uri 
class HttpResponseTemporaryRedirect(HttpResponse): 
    status_code = 307 

    def __init__(self, redirect_to): 
     HttpResponse.__init__(self) 
     self['Location'] = iri_to_uri(redirect_to) 

Xem thêm django.http module.

Edit:

trên các phiên bản gần đây Django, thay đổi iri_to_uri nhập khẩu:

from django.utils.encoding import iri_to_uri 
+0

Phiên bản mới hơn của Django có chuyển hướng vĩnh viễn HttpResponsePermanentRedirect nhưng không chắc chắn nếu nó giải quyết được vấn đề ban đầu https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponsePermanentRedirect – JiminyCricket

+0

vĩnh viễn là 301, vậy, không. – Lloeki

1

Chỉ cần gọi cái nhìn mới của bạn từ quan điểm cũ của bạn bằng cách sử dụng đối tượng yêu cầu tương tự. Tất nhiên nó sẽ không dẫn đến một chuyển hướng như vậy, nhưng nếu tất cả các bạn quan tâm là 'chuyển' dữ liệu từ một cái nhìn khác, sau đó nó sẽ làm việc.
Tôi đã thử nghiệm đoạn mã sau và nó hoạt động.

from django.views.generic import View 

class MyOldView(View): 
    def post(self, request): 
     return MyNewView().post(request) 

class MyNewView(View): 
    def post(self, request): 
     my_data = request.body 
     print "look Ma; my data made it over here:", my_data 
+0

Tôi đã sử dụng giải pháp này và nó đã được làm việc không có vấn đề. – guival

0

Bạn có thể sử dụng làmbối cảnh với với nó:

Render(request,"your template path",  {'vad name' : var value} 

Bạn có thể recive vars trong mẫu:

{% If var name %} 
{{ var name }} 
{% endif %} 
5

sử dụng requests gói.rất dễ dàng để thực hiện

pip install requests 

sau đó bạn có thể gọi bất kỳ các url với bất kỳ phương pháp và truyền dữ liệu

trong quan điểm của bạn nhập các yêu cầu của nó

import requests 

để gửi dữ liệu, hãy làm theo các định dạng

r = requests.post('http://yourdomain/path/', data = {'key':'value'}) 

để nhận url tuyệt đối ở chế độ xem django, hãy sử dụng

request.build_absolute_uri(reverse('view_name'))

Như vậy mã xem django trông giống như

r = requests.post(
      request.build_absolute_uri(reverse('view_name')), 
      data = {'key':'value'} 
    ) 

nơi r là đối tượng phản ứng với status_codecontent thuộc tính. r.status_code cung cấp mã trạng thái (thành công sẽ là 200) và r.content cung cấp cho cơ thể phản hồi. Có một phương pháp json (r.json()) mà sẽ chuyển đổi đáp ứng với định dạng json

requests

requests.post

Các vấn đề liên quan