2010-08-18 34 views
14

vì vậy tôi đã tự hỏi nếu bạn có thể trả lại một thẻ bao gồm trực tiếp từ một khung nhìn.Django - Rendering Inclusion Tag từ một View

Trang này là trang bình thường có danh sách các mục. Danh sách các mục được hiển thị bằng cách sử dụng thẻ bao gồm. Nếu yêu cầu ajax được thực hiện cho chế độ xem, tôi muốn chỉ trả lại thẻ bao gồm những gì sẽ trả lại để tôi có thể thêm nó vào trang thông qua javascript. Có phải bất cư thứ gì như thế này đều được? Hoặc tôi nên kiến ​​trúc sư này tốt hơn?

Trả lời

0

Điều này chắc chắn có thể xảy ra. Chế độ xem có thể hiển thị bất kỳ mẫu nào mà thẻ bao gồm có thể. Ưu điểm của phương pháp này là bạn có thể tận dụng toàn bộ sức mạnh của các mẫu của Django.

Mặt khác, các phản hồi AJAX thường không chứa HTML nhiều như XML/JSON. Nếu bạn đang sử dụng các tính năng của Django, bạn nên sử dụng HTML. Nếu không, XML/JSON có thể có ý nghĩa hơn. Chỉ cần hai xu của tôi.

+0

Tôi luôn gặp sự cố khi trả về xml/json và sau đó có javascript hiển thị dữ liệu thành html. Không phải là vi phạm các nguyên tắc DRY gây ra bây giờ chúng tôi có mã nhân đôi trong mẫu django và trong javascript. – killerbarney

+0

Bạn đề cập đến nó có thể được thực hiện, nhưng bạn không bao gồm một ví dụ. Bạn có thể chỉ cho tôi cách để làm điều đó hoặc một trang có nó? – killerbarney

0

cách nhanh chóng và bẩn có thể có chế độ xem, hiển thị mẫu, chỉ chứa templatetag của bạn.

+0

ya, cách này dường như dư thừa trong mã, đang hy vọng một điều gì đó không liên quan đến bước bổ sung đó. – killerbarney

+0

sau đó hiển thị các mô hình được tuần tự hóa dưới dạng json, hãy xem http://code.google.com/p/django-rest-interface/ để bắt đầu hoặc cuộn ứng dụng của riêng bạn, sử dụng một không gian tên URL khác thay vì phân nhánh trong hiện tại của bạn lượt xem! – sjh

1

Tôi đã cố gắng để làm điều chính xác cùng một ngày hôm nay, và đã kết thúc viết một hàm helper để render mẫu thẻ:

def render_templatetag(request, tag_string, tag_file, dictionary=None): 
    dictionary = dictionary or {} 
    context_instance = RequestContext(request) 
    context_instance.update(dictionary) 
    t = Template("{%% load %s %%}{%% %s %%}" % (tag_file, tag_string)) 
    return t.render(context_instance) 

tag_string là cuộc gọi đến mẫu thẻ vì nó sẽ xuất hiện trong một bình thường mẫu và tag_file là tệp bạn cần tải cho thẻ mẫu.

+0

điều này là vô nghĩa, việc hiển thị thẻ phải được thực hiện trong một mẫu thay vì trong mã xem. bạn có thể sử dụng thẻ bao gồm để tránh trùng lặp mã mẫu. – Anentropic

+0

Thực hiện theo cách này, bạn sẽ không phải lặp lại tên của mẫu được hiển thị trong chế độ xem của bạn –

+0

@Craig vâng nhưng bạn phải lặp lại chuỗi thẻ được sử dụng trong mẫu trong chế độ xem của mình thay vào đó, nó không còn là DRY nữa – Anentropic

2

này nghe có vẻ như một công việc cho các render_to_string hoặc render_to_response phím tắt:
https://docs.djangoproject.com/en/dev/ref/templates/api/#the-render-to-string-shortcut
https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#django.shortcuts.render_to_response

Chúng tôi vẫn có thể sử dụng thẻ bao gồm để tạo ra một dict mẫu bối cảnh từ args của chúng tôi (như cách hữu ích chỉ ra bởi @BobStein -VisiBone trong ý kiến)

from django.template.loader import render_to_string 
from django.shortcuts import render_to_response 

from .templatetags import my_inclusion_tag 


rendered = render_to_string('my_include.html', my_inclusion_tag(foo='bar')) 

#or 

def my_view(request): 
    if request.is_ajax(): 
     return render_to_response('my_include.html', 
         my_inclusion_tag(foo='bar'), 
         context_instance=RequestContext(request)) 
+0

Thực hiện theo cách này, bạn phải lặp lại tên của mẫu được hiển thị trong chế độ xem của bạn, nguyên tắc này sẽ phá vỡ nguyên tắc DRY –

+0

@Xoá việc lấy lại DRY là không đáng kể, chỉ lưu tên của mẫu trong biến và sử dụng var trong cả dạng xem của bạn và vị trí thẻ bao gồm được xác định – Anentropic

+1

Không phải OP đã đưa ra bất kỳ ví dụ nào để bắt đầu, nhưng những gì còn thiếu của bạn là bất kỳ đề cập đến chức năng thẻ bao gồm. Hóa ra rằng mặc dù nó được trang trí, nó vẫn có thể được gọi trực tiếp để xuất ra một từ điển sẵn sàng cho render_to_string(). Tôi đề nghị thay thế cả hai từ điển trong mã của bạn bằng: 'my_inclusion_tag_function (arguments)' và thêm ở đầu 'từ templatetags.my_file bao gồm my_inclusion_tag_function' hoặc cái gì đó. –

0

Sử dụng inclusion tag with configurable template decorator provided by Gonz thay cho các thẻ bao gồm mặc định của Django bạn có thể viết một helper theo quan điểm của bạn:

from django.template.loader import render_to_string 
from home.templatetags.objectwidgets import object_widget 

def _object_widget(request, obj): 
    template, context = object_widget(RequestContext(request), obj) 
    return render_to_string(template, context) 

Đó là DRY và hoạt động với Django 1.3 (Tôi chưa thử nghiệm với Django 1.4).

Tôi sử dụng kỹ thuật này để trả lại kết quả tìm kiếm được hiển thị bằng HTML qua các cuộc gọi JSON/AJAX (không có gì tốt hơn mà tôi đã đưa ra).

0

Có thể, nhưng có thể hơi khó hiểu, phức tạp hoặc phức tạp.

Những gì tôi đề nghị, là kiến ​​trúc sư nó để bạn có phần hiển thị trong hàm utils.py và sử dụng nó trong một simple_tag thay vì bao gồm_tag. Bằng cách này, bạn có thể sử dụng cùng một hàm render utils dễ dàng trong các khung nhìn.

Trong ví dụ tưởng tượng (rất đơn giản) của tôi, tôi có danh sách người dùng và nút "Tải thêm" trả về nhiều người dùng hơn.

tài khoản/utils.py

from django.template.loader import render_to_string 


def render_users(users): 
    return render_to_string("account/user_list_items.html", {"users": users}) 

tài khoản/templatetags/account_tags.py

from django import template 

from ..utils import render_users 

register = template.Library() 


@register.simple_tag 
def list_users(users): 
    return render_users(users) 

tài khoản/views.py

from django.http import HttpResponse 

from .models import User 
from .utils import render_users 


def load_more_users(request): 
    limit = request.GET["limit"] 
    offset = request.GET["offset"] 
    users = User.objects.all()[offset:offset + limit] 
    return HttpResponse(render_users(users)) 

Đơn giản là tốt hơn so với phức tạp.