2009-09-29 22 views
5

Một ngày khác tôi đã viết một số AJAX cho một ứng dụng Django mà tôi đã và đang làm việc.một cách tốt hơn để làm ajax trong django

Tôi đến từ Ruby on Rails, vì vậy tôi đã không làm nhiều theo cách của JS thô.

Vì vậy, dựa trên Rails' partials, tôi một cái gì đó tương tự như sau trong một loại giả, không đổ mồ hôi các chi tiết:

1) chức năng JS sử dụng Ajax.Updater nguyên mẫu của ('tablediv' là id của bảng tôi muốn cập nhật Ajaxily, và url trỏ đến quan điểm django thích hợp)

function updateTable(){ 
     new Ajax.Updater('tablediv',url {params: params....etc 

2) xem django rằng có dữ liệu mới để cư bảng với:

def ajaxTable 
    objects = Objects.object.all... 
    return render_to_response('ajaxtable.html',objects) 

3) ajaxtable.html chỉ là một loại Rails "một phần" vì vậy về cơ bản một bảng w/o <table></table> ...:

<th>{{object.data}}</th> 
    <td>{{object.moredata}}</td> 

như vậy để câu hỏi thực tế của tôi:

Điều này dường như hacky với tôi Tôi đã ném nó lại với nhau sau khi mệt mỏi vì tìm kiếm trực tuyến những gì tôi muốn.

Đây có phải là cách thực hiện? Nó hoạt động tốt, tôi chỉ không biết đủ để biết, bạn biết không?

Trả lời

1

Chính xác thì có vẻ gì về nó? Có vẻ như một cách hoàn toàn hợp lệ để làm điều gì đó.

Tôi đoán một giải pháp thay thế sẽ là serialising thành json và gửi lại cho đoạn mã javascript templating.

+0

Đó là những gì tôi đã chơi xung quanh với, nhưng tại thời điểm tôi không biết javascript nhiều như tôi biết, vì vậy chỉ cần gửi các đối tượng như JSON, làm cho đối tượng javascript literals ra khỏi nó, và sau đó tablediv.innerHTML = foo ? – Joel

+0

JSON * là * một đối tượng theo nghĩa đen vì vậy điều tốt đẹp về việc sử dụng nó trong javascript là bạn không phải làm bất cứ điều gì với nó để thực sự sử dụng nó khi bạn có nó. Tôi thích sử dụng JSON kết hợp với hệ thống templating mà tôi đã liên kết ở trên (jquery, không phải prototype, xin lỗi) vì bạn có thể chuyển JSON trở lại thẳng vào template mà bạn thiết lập và nó sẽ hoạt động. – Steerpike

2

Không có vấn đề gì, bạn sẽ cần ít nhất hai điều:

  1. mã javascript của bạn để thực hiện cuộc gọi (bạn có điều này)

  2. Server side mã để xử lý yêu cầu (đây là chế độ xem của bạn và url-config)

Hoàn toàn không có gì "hack" về điều này.

Điều thứ ba, tệp mẫu của bạn, là tùy chọn - nhưng thường là thực hành tốt. Bạn muốn tách đánh dấu của mình khỏi mã, vì nhiều lý do.

Vì vậy, tôi nghĩ bạn đã có ý tưởng đúng. Tiếp tục.

+0

tốt đẹp, cảm ơn cho phản ứng, tôi đã hoàn thành dự án và chuyển sang, nhưng nó đã kinda bugged tôi kể từ đó (khi tôi đang ở giữa một cái gì đó tôi không thể dừng lại để yêu cầu trên một diễn đàn hoặc ngăn xếp tràn .. Tôi don không có sự kiên nhẫn :), tốt để biết rằng bản năng của tôi không hoàn toàn ridiculus – Joel

5

Nó kinda phụ thuộc vào những gì bạn muốn làm tôi nghĩ. Ajax là khá nhiều kịch bản từ Google Maps đến việc tự động hoàn thành đơn giản thay đổi rất nhiều về độ phức tạp và cách tiếp cận tốt nhất.

Tuy nhiên, có một số điều hữu ích bạn có thể thực hiện trợ giúp đó.

1) mức Template

Hãy chắc chắn rằng bạn đã "django.core.context_processors.request" trong bối cảnh TEMPLATE_CONTEXT_PROCESSORS của bạn.Sau đó, bạn có thể làm điều này;

{% if not request.is_ajax %} 
<html> 
    <head> 
    ... 
    </head> 
    <body> 
    ... 
{% endif %} 
actual content 
{% if not request.is_ajax %} 
</body> 
</html> 
{% endif %} 

Về cơ bản, bạn có thể yêu cầu trình duyệt và nhận nội dung đầy đủ hoặc yêu cầu qua JavaScript và chỉ nhận nội dung. Có một blogpost ở đâu đó giải thích điều này chi tiết hơn nhưng tôi không thể tìm thấy nó vào lúc này.

2) Trong chế độ xem

Trong mẫu, chúng tôi chỉ truy cập đối tượng yêu cầu trong mẫu. Theo quan điểm, bạn có thể làm những việc rất giống nhau.

def my_view(request): 
    if requst.is_ajax(): 
     # handle for Ajax requests 

    # otherwise handle 'normal' requests 
    return HttpResponse('Hello world') 

Các phương pháp trên không thực sự khác so với bạn nhưng cho phép bạn sử dụng lại chế độ xem và viết chính xác hơn một chút. Tôi sẽ không thực sự nói những gì bạn đang làm là sai hoặc hacky nhưng bạn có thể viết nó để làm cho nó ngắn gọn hơn và tái sử dụng các mẫu và khung nhìn. Ví dụ:

nói rằng bạn chỉ có thể có một mẫu và nếu yêu cầu Ajax của nó có mẫu chỉ trả về phần cần được cập nhật. Trong trường hợp của bạn, nó sẽ là các khung nhìn bảng.

+0

Điều đó có vẻ thực sự thông minh, đến từ việc sử dụng ruby ​​nhúng hấp dẫn tôi ... có thể quá thông minh ... – Joel

+0

haha ​​no html trong các ý kiến ​​... – Joel

+0

quá thông minh? Tôi thực sự rất thích nó. Bạn hoàn toàn có thể Ajaxify các bit lớn của một trang web một cách nhanh chóng, tiếc là không có cách nào để có nhiều hơn một 'khối ajax' cho mỗi mẫu ... hmm Tôi tự hỏi làm thế nào bạn có thể làm điều đó. –

4

Tôi khá muộn, nhưng tôi muốn ghi lại cách kết hợp và điều chỉnh các giải pháp được trình bày bởi d0ugal theo cách nào đó, nó sẽ giải quyết mẫu mã sạch hơn nhiều.

Tôi có một mô hình đại diện cho người liên hệ.

The (generic) nhằm có được một ContactPerson trông như thế này:

def contcactperson_detail_view(request, name): 
    try: 
     person = ContactPerson.objects.get(slug=name) 
    except: 
     raise Http404 
    if request.is_ajax(): 
     return contcactperson_detail_view_ajax(request, person) 
    return list_detail.object_detail(
      request, 
      queryset = ContactPerson.objects.all(), 
      object_id = person.id, 
      template_object_name = "contactperson", 
     ) 

@render_to('cms/contactperson_detail_ajax.html')  
def contcactperson_detail_view_ajax(request, person): 
    return {'contactperson':person, 'is_ajax':True} 

Các mẫu sẽ hiển thị quan điểm cho rằng xử lý một ContactPerson được gọi contcactperson_detail_view.html:

{% extends "index.html" %} 
{% block textpane %} 

<h1 id="mainheader">{{ contactperson.first_name }} {{ contactperson.family_name }} </h1> 
<div class="indentation">&nbsp;</div> 
{% include 'cms/contactperson_detail_photo.html' %}                           
<div id="text_pane"> 

{% include 'cms/contactperson_detail_textpane.html' %} 
</div> 
{% endblock %} 

Nó bao gồm hai tiểu mẫu

contactperson_detail_textpane.html 


<p>{{ contactperson.description }}</p> 
<ul> 
    <li> 
     <dl> 
      <dt>Email</dt> 
      <dd> 
       {{ contactperson.mail }} 
      </dd> 
     </dl> 
    </li> 
    <li> 
     <dl> 
      <dt>Contact Person for</dt> 
      <dd> 
       <ul> 
       {% for c in contactperson.categories.all %} 
        <li><a href="{% url category-view c.slug %}">{{ c }}</a></li> 
       {% endfor %} 
       </ul> 
      </dd> 
     </dl> 
    </li> 
</ul> 

contactperson_detail_photo.html

{% with contactperson.photo.detailphoto as pic %} 
    {% with pic.url as pic_url %}  
    <div {% if not is_ajax %}id='imageContainer'{% endif %} style="float: right;padding-right:0.5em; 
            padding-bottom: 1em; padding-left:0.5em;clear:both; 
            width:{{ pic.width }}px"> 
     <div style="width:{{ pic.width}}px">      
       <img style="clear:both" src="{{ pic_url }}" alt="{{ i.name }}"/> 
     </div>                              
    </div> 
    {% endwith %} 
{% endwith %} 

3 mẫu này sẽ được sử dụng nếu yêu cầu không phải là ajax.

Nhưng nếu yêu cầu là ajax, contcactperson_detail_view sẽ trả lại chế độ xem contcactperson_detail_view_ajax, sử dụng mẫu contactperson_detail_ajax.html để hiển thị. Và mẫu này trông giống như sau:

<h1>{{ contactperson.first_name }} {{ contactperson.family_name }}</h1> 
{% include 'cms/contactperson_detail_photo.html' %}                           
{% include 'cms/contactperson_detail_textpane.html' %} 

Vì vậy, nó sử dụng cùng một mẫu phụ nhưng không mở rộng bất kỳ thứ gì, do đó chỉ đánh dấu cần thiết được phân phối. Khi chế độ xem ajax vượt qua is_ajax = True đối với mẫu, nó có thể được sử dụng để điều chỉnh những thứ nhỏ, như thiết lập các thuộc tính id chính xác.

Không cần bộ xử lý ngữ cảnh hoặc url bổ sung.

Cuối cùng mã Javascript:

$("#contact_person_portlet a").click(function(event){ 
     event.preventDefault(); 
     $.ajax({ 
      type: "GET", 
      url: event.target.getAttribute('href'), 
      success: function(msg){ 
       overlay(msg); 
      } 
     }); 
    }); 

Hy vọng rằng nó sẽ hữu ích cho một số người. Nếu vậy, xin vui lòng để lại một bình luận!

+0

Tôi tin rằng bạn có thể triển khai giải pháp đơn giản hơn bằng cách sử dụng một chế độ xem duy nhất và cùng một mẫu cho ajax/non-ajax, nhưng kế thừa từ một mẫu cơ sở khác tùy thuộc vào biến ngữ cảnh. Xem http://stackoverflow.com/questions/4014156/django-templates-sysntax-error/4018629#4018629 cho một phản hồi mà tôi đã đưa ra cho một câu hỏi khác trong dòng đó –

+0

thực sự rất thanh lịch – vikingosegundo

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