2008-11-23 30 views
11

Trong trường hợp cụ thể của tôi, tôi có hai loại "thông báo" mà tôi cần phải thử lại và phân trang.Sử dụng django làm cách nào tôi có thể kết hợp hai truy vấn từ các mô hình riêng biệt thành một truy vấn?

Hãy bỏ qua các chi tiết, và chỉ nói rằng các loại đầu tiên là trong một mô hình gọi là Msg1 và người kia được gọi là msg2

Các lĩnh vực của hai mô hình này là hoàn toàn khác nhau, các lĩnh vực duy nhất mà là chung cho các hai mô hình là "ngày" và "tiêu đề" (và tất nhiên, id).

Tôi có thể nhận được Msg1.objects.all()Msg2.objects.all() nhưng tôi có thể kết hợp hai truy vấn này thành một truy vấn, sắp xếp nó theo ngày và phân trang không?

Tôi cần phải duy trì tính chất lười biếng của truy vấn.

Giải pháp tầm thường là list(query) cả hai truy vấn và kết hợp chúng trong danh sách python. nhưng điều này không hiệu quả vì những lý do hiển nhiên.

Tôi đã xem qua các tham chiếu django về các mô hình và dp-api, nhưng dường như không có cách nào để kết hợp các truy vấn của các mô hình/bảng khác nhau thành một.

+0

"không hiệu quả vì lý do rõ ràng" Thật sao? Bạn có số liệu không? Tôi hỏi vì không có lý do rõ ràng tại sao nó sẽ không hiệu quả. –

+0

Tôi nghĩ vì một khi bạn liệt kê (truy vấn) nó nhận được tất cả các kết quả, và anh ta muốn để điều đó càng muộn càng tốt. –

+0

không hiệu quả vì nó truy cập cơ sở dữ liệu cho TẤT CẢ các mục, (có thể là 1000) trong khi chỉ hiển thị 20 trên mỗi trang hoặc như vậy .. – hasen

Trả lời

11

tôi sẽ đề nghị bạn sử dụng Model inheritance.

Tạo mô hình cơ sở chứa ngày và tiêu đề. Subclass Msg1 và Msg2 tắt nó như mô tả. Làm tất cả các truy vấn của bạn (để điền vào một trang) bằng cách sử dụng mô hình cơ sở và sau đó chuyển sang loại có nguồn gốc ở thời điểm cuối cùng.

Điều thực sự tuyệt vời về kế thừa là django sau đó cho phép bạn sử dụng mô hình cơ sở trong khóa ngoài từ các mô hình khác, vì vậy bạn có thể làm cho toàn bộ ứng dụng của bạn linh hoạt hơn. Dưới mui xe nó chỉ là một bảng cho mô hình cơ bản với một bảng cho mỗi mô hình con chứa các khóa một-một.

+1

Điều gì sẽ xảy ra nếu lớp cơ sở của tôi trừu tượng? Bạn có thể hiển thị một số ví dụ về mã không? –

2

"kết hợp hai truy vấn này thành một truy vấn, sắp xếp nó theo ngày và phân loại nó?"

  1. Đó là công đoàn SQL. Rời khỏi Django ORM và sử dụng một công đoàn SQL. Nó không phải là nhanh chóng tuyệt vời bởi vì SQL đã tạo ra một kết quả tạm thời, mà nó sắp xếp.

  2. Tạo kết quả tạm thời, có thể được sắp xếp. Vì danh sách có phương thức sắp xếp, bạn sẽ phải hợp nhất hai kết quả vào một danh sách.

  3. Viết thuật toán hợp nhất chấp nhận hai bộ truy vấn, phân trang kết quả.


Chỉnh sửa. Đây là thuật toán hợp nhất.

def merge(qs1, qs2): 
    iqs1= iter(qs1) 
    iqs2= iter(qs2) 
    k1= iqs1.next() 
    k2= iqs2.next() 
    k1_data, k2_data = True, True 
    while k1_data or k2_data: 
     if not k2_data: 
      yield k1 
      try: 
       k1= iqs1.next() 
      except StopIteration: 
       k1_data= False 
     elif not k1_data: 
      yield k2 
      try: 
       k2= iqs2.next() 
      except StopIteration: 
       k2_data= False 
     elif k1.key <= k2.key: 
      yield k1 
      try: 
       k1= iqs1.next() 
      except StopIteration: 
       k1_data= False 
     elif k2.key < k1.key: # or define __cmp__. 
      yield k2 
      try: 
       k2= iqs2.next() 
      except StopIteration: 
       k2_data= False 
     else: 
      raise Exception("Wow...") 

Bạn có thể gấp pagination:

def paginate(qs1, qs2, start=0, size=20): 
    count= 0 
    for row in merge(qs1, qs2): 
     if start <= count < start+size: 
      yield row 
     count += 1 
     if count == start+size: 
      break 
+0

Nếu bạn theo con đường này, bạn muốn thực hiện sắp xếp trước công đoàn trong lệnh SQL (vì SQL có thể sử dụng các chỉ mục để tăng tốc sắp xếp) và hy vọng bạn có thể giới hạn kết quả sắp xếp trung gian trước khi kết hợp, giảm kích thước của bất kỳ dữ liệu tạm thời nào. –

+0

Tuy nhiên, vì Liên minh có thể * bất kỳ * kết hợp các bảng, phép tính, chữ, vv, một liên kết * phải * tạo và sắp xếp kết quả trung gian. Có lẽ bạn có thể tối ưu hóa, nhưng phiên bản chung * phải * hoạt động. –

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