2009-12-03 24 views
12

Tôi muốn có thể tạo mẫu từ một tệp (có lẽ là sử dụng django.template.loader.get_template (tên tệp)), và sau đó xác định tập hợp các biến cần được xác định trong bất kỳ ngữ cảnh nào được truyền.Truy vấn mẫu cho các biến cần thiết?

Tôi nghĩ rằng sẽ có một phương pháp trên đối tượng Mẫu, nhưng dường như không có.

Tôi đọc các tài liệu, và gần nhất tôi thấy được điều này:

http://docs.djangoproject.com/en/1.0/topics/templates/#using-the-built-in-reference

mà đề nghị đi đến giao diện quản trị để xem tất cả các biến gắn liền với một cái nhìn nhất định.

Tôi không muốn đi qua giao diện quản trị vì tôi muốn thực hiện việc này theo lập trình - tôi đang cố gắng viết các bài kiểm tra.

Tôi đang sử dụng phiên bản Django (1, 0, 2, 'chính thức', 0)

Cập nhật:

Tôi cố gắng trả lời synack và phát hiện ra rằng (với sự thay thế của filter_expression.token bởi FILTER_EXPRESSION .var, để lấy tên thực tế của biến mà không có thẻ và vv) nó trả về các biến được định nghĩa cục bộ trong khuôn mẫu, nhưng không làm việc cho các biến được định nghĩa trong cha mẹ mà nó mở rộng.

Vì vậy, ví dụ, giả sử tôi có mẫu trong hai tập tin:

toyparent.html:

{%block base_results%} 
Django is {{adjective}} 
{%endblock base_results%} 

toychild.html:

{% extends "toyparent.html" %} 

{%block base_results%} 
    {{block.super}} 
    I {{verb}} it. 
{%endblock base_results %} 

Và tôi tải các mẫu trẻ:

>>> toy=django.template.loader.get_template('toychild.html') 

này làm cho đúng:

>>> toy.render(django.template.Context(dict(adjective='cool',verb='heart'))) 
u'\n \nDjango is cool\n\n I heart it.\n\n' 

Nhưng tôi không thể có được hai biến từ nó:

>>> v=toy.nodelist.get_nodes_by_type(VariableNode) 
>>> for k in v: print k.filter_expression.var 
... 
block.super 
verb 

Trả lời

20

Bạn có thể kiểm tra bằng mắt một mẫu và quan sát sự hiện diện của bất kỳ "Node Variable" đối tượng trong nodelist của mẫu đó:

>>> from django.template import Template, Context 
>>> t = Template("Django is {{ adjective }} and I {{ verb }} it.") 
>>> t.nodelist 
[<Text Node: 'Django is '>, <Variable Node: adjective>, <Text Node: ' and I '>, <Variable Node: verb>, <Text Node: ' it.'>] 

Đây là loại có thể được nhập trực tiếp để so sánh. Bất kỳ cá thể Node nào đều có phương thức get_nodes_by_type() có thể được gọi chống lại một nodelist, trả về tất cả các nút thuộc loại đó cho mẫu. Ví dụ:

>>> from django.template import VariableNode 
>>> varnodes = t.nodelist.get_nodes_by_type(VariableNode) 
>>> varnodes 
[<Variable Node: adjective>, <Variable Node: verb>] 

Vì vậy, bây giờ bạn có danh sách các biến cho mẫu. Điều này sẽ cần phải được thực hiện một bước xa hơn để trích xuất tên thực tế của mỗi biến mà không cần phải thực hiện các thủ thuật cắt chuỗi ngu ngốc trên các tên repr của chúng.

Tên biến bản thân được lưu trữ trong filter_expression.token cho mỗi VariableNode:

>>> varnodes[0].filter_expression.token 
u'adjective' 

Và do đó, một danh sách hiểu đơn giản được chúng tôi tất cả các tên biến cho mẫu:

>>> template_vars = [x.filter_expression.token for x in varnodes] 
>>> template_vars 
[u'adjective', u'verb'] 

Vì vậy, không giải pháp đơn giản nhất, nhưng nếu có một cách tốt hơn tôi không biết về nó.

Phần thưởng: Chức năng !!

from django.template import VariableNode 
def get_template_vars(t): 
    varnodes = t.nodelist.get_nodes_by_type(VariableNode) 
    return [x.filter_expression.token for x in varnodes] 

Ok, nó không quá phức tạp sau tất cả!

Follow-up Edit: Bắt biến từ các mẫu mẹ

(Điều này theo dõi được sử dụng thông tin từ các câu hỏi được cập nhật).

Đây là nơi nó thực sự trở nên phức tạp bởi vì nút thắt của mẫu đồ chơi là một đơn ExtendsNode (trong trường hợp này).

>>> toy.nodelist 
[<ExtendsNode: extends "mysite/toyparent.html">] 

Tôi sẽ tưởng tượng rằng trong các mẫu lớn hơn có thể có nhiều đối tượng ExtendsNode. Nhưng dù sao, nếu bạn kiểm tra việc ExtendsNode, và trích xuất các mẫu cha mẹ từ nó, bạn có thể đối xử với phụ huynh giống như ví dụ ban đầu của tôi:

>>> enode = toy.nodelist[0] 
>>> enode.parent_name 
u'mysite/toyparent.html' 
>>> parent = enode.get_parent(enode.parent_name) 
>>> parent 
<django.template.Template object at 0x101c43790> 
>>> parent.nodelist.get_nodes_by_type(VariableNode) 
[<Variable Node: adjective>] 

Và có biến adjective của bạn được chiết xuất từ ​​các mẫu mẹ. Để thực hiện một thử nghiệm chống lại một ExtendsNode bạn có thể nhập những lớp từ django.template.loader_tags:

>>> from django.template.loader_tags import ExtendsNode 
>>> ext = toy.nodelist.get_nodes_by_type(ExtendsNode) 
>>> ext 
[<ExtendsNode: extends "mysite/toyparent.html">] 

Vì vậy, bạn có thể làm một số xét nghiệm đối với mẫu cho sự hiện diện của một ExtendsNode và đi ngược với mẫu phụ huynh và cá nhân có được những tên biến . Tuy nhiên, điều này đang bắt đầu dường như giống như một con giun.

Ví dụ, nếu bạn đã làm điều này:

>>> toy.nodelist.get_nodes_by_type((ExtendsNode, VariableNode)) 
[<ExtendsNode: extends "mysite/toyparent.html">, <Variable Node: block.super>, <Variable Node: verb>] 

Bây giờ bạn đã có ExtendsNodeVariableNode đối tượng và nó chỉ bắt đầu để có được bối rối. chúng ta làm gì sau đó? Chúng tôi có cố gắng bỏ qua bất kỳ biến số block nào được trả về từ các thử nghiệm như vậy không? Tôi không biết!!

Trong mọi trường hợp, đây là thông tin bạn muốn, nhưng tôi không nghĩ rằng đây là giải pháp thiết thực. Tôi nhấn mạnh rằng vẫn có thể là một cách tốt hơn. Nó có thể là giá trị nhìn vào những gì bạn đang cố gắng để giải quyết và xem nếu có một cách tiếp cận bạn có thể mất.

+0

Xin cảm ơn - điều này gần nhưng dường như không hoạt động đúng cho kế thừa - hãy xem mô tả sự cố mở rộng ở trên. –

+1

Ahh, bạn nói đúng. Tôi thậm chí không xem xét các phần mở rộng mẫu. Hãy để tôi poke xung quanh và xem nếu tôi có thể tìm ra nó. – jathanism

+1

Wow, nghiên cứu và thông tin tuyệt vời. +1 –

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