2008-10-21 32 views
62

tôi cần phải thực hiện một truy vấn lọc từ bên trong một mẫu django, để có được một tập các đối tượng tương đương với mã python trong một lần xem:Làm thế nào để thực hiện lọc truy vấn trong các mẫu django

queryset = Modelclass.objects.filter(somekey=foo) 

Trong mẫu của tôi, tôi muốn làm

{% for object in data.somekey_set.FILTER %} 

nhưng tôi dường như không thể tìm ra cách viết LỌC.

Trả lời

98

Bạn không thể làm điều này, theo thiết kế. Các tác giả của khung công tác Django dự định phân tách chặt chẽ mã trình bày khỏi logic dữ liệu. Các mô hình lọc là logic dữ liệu và xuất HTML là logic trình bày.

Vì vậy, bạn có một số tùy chọn. Cách dễ nhất là thực hiện lọc, sau đó chuyển kết quả đến render_to_response. Hoặc bạn có thể viết một phương thức trong mô hình của mình để có thể nói {% for object in data.filtered_set %}. Cuối cùng, bạn có thể viết thẻ mẫu của riêng bạn, mặc dù trong trường hợp cụ thể này, tôi sẽ khuyên bạn nên chống lại điều đó.

+2

Cám ơn làm rõ khái niệm thiết kế django. Tôi đang sử dụng phương pháp phương pháp mô hình. – Ber

+2

Xin chào mọi người là 2014 ngay bây giờ! Khoảng 6 năm sau, các thư viện JS đã đạt được tiến bộ rất lớn và việc lọc dữ liệu không quá lớn nên được thực hiện tốt hơn ở phía máy khách với sự hỗ trợ của một số thư viện java script hay ít nhất là AJAX-ed. – andi

+1

@andi: Tôi chắc chắn đồng ý với các tập dữ liệu lớn vừa phải, ví dụ: thậm chí hàng ngàn hàng trong một bảng. Đã làm việc trên cơ sở dữ liệu với hàng triệu hàng, vẫn có một nơi để lọc phía máy chủ :) –

11

Tôi gặp sự cố này thường xuyên và thường sử dụng giải pháp "thêm phương pháp". Tuy nhiên, chắc chắn có trường hợp "thêm phương thức" hoặc "tính toán nó trong chế độ xem" không hoạt động (hoặc không hoạt động tốt). Ví dụ. khi bạn đang lưu vào bộ đệm mẫu và cần một số tính toán DB không tầm thường để tạo ra nó. Bạn không muốn làm DB làm việc trừ khi bạn cần, nhưng bạn sẽ không biết liệu bạn có cần đến khi bạn đang ở sâu trong logic mẫu hay không.

Một số giải pháp khác có thể:

  1. Sử dụng {% expr < expression> như < var_name>%} mẫu thẻ tìm thấy tại http://www.djangosnippets.org/snippets/9/ Biểu thức là bất kỳ biểu hiện Python pháp lý với bối cảnh của mẫu của bạn như phạm vi địa phương của bạn .

  2. Thay đổi trình xử lý mẫu của bạn. Jinja2 (http://jinja.pocoo.org/2/) có cú pháp gần giống với ngôn ngữ mẫu Django, nhưng với đầy đủ sức mạnh Python có sẵn. Nó cũng nhanh hơn. Bạn có thể thực hiện việc bán buôn này hoặc bạn có thể giới hạn việc sử dụng các mẫu đó bạn đang hoạt động nhưng sử dụng các mẫu "an toàn" của Django cho các trang được thiết kế duy trì.

6

Tùy chọn khác là nếu bạn có bộ lọc mà bạn luôn muốn áp dụng, hãy thêm custom manager vào mô hình được đề cập luôn áp dụng bộ lọc cho kết quả được trả về.

Một ví dụ điển hình là mô hình Event, trong đó 90% truy vấn bạn thực hiện trên mô hình bạn sẽ muốn một cái gì đó như Event.objects.filter(date__gte=now), tức là bạn thường quan tâm đến số Events sắp tới. Điều này sẽ trông giống như:

class EventManager(models.Manager): 
    def get_query_set(self): 
     now = datetime.now() 
     return super(EventManager,self).get_query_set().filter(date__gte=now) 

Và trong mô hình:

class Event(models.Model): 
    ... 
    objects = EventManager() 

Nhưng một lần nữa, điều này áp dụng các bộ lọc tương tự chống lại tất cả các truy vấn mặc định thực hiện trên mô hình Event và như vậy là không được linh hoạt một số các kỹ thuật được mô tả ở trên.

8

Điều này có thể được giải quyết với một thẻ bài tập:

from django import template 

register = template.Library() 

@register.assignment_tag 
def query(qs, **kwargs): 
    """ template tag which allows queryset filtering. Usage: 
      {% query books author=author as mybooks %} 
      {% for book in mybooks %} 
      ... 
      {% endfor %} 
    """ 
    return qs.filter(**kwargs) 
22

tôi chỉ bổ sung thêm một mẫu thẻ như thế này:

@register.filter 
def in_category(things, category): 
    return things.filter(category=category) 

Sau đó, tôi có thể làm:

{% for category in categories %} 
    {% for thing in things|in_category:category %} 
    {{ thing }} 
    {% endfor %} 
{% endfor %} 
+0

Tôi đang cố gắng giải pháp này nhưng nó tiếp tục kích hoạt một lỗi: ''cho' báo cáo nên sử dụng định dạng 'cho x trong y': cho p trong r | people_in_roll_department: d'. Bất kỳ ý tưởng? – diosney

+1

Bị mắc kẹt bởi một lỗi khó chịu: (https://code.djangoproject.com/ticket/19882 – diosney

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