2010-02-04 47 views
9

django có ORM phức tạp này được xây dựng trong nó, nhưng sau khi dành nhiều thời gian vào nó, nó vẫn còn khó khăn cho tôi để làm cho các truy vấn được đáng kể đơn giản trong SQL. Thậm chí còn có một số điều đơn giản mà tôi không thể tìm thấy cách để thực hiện thông qua ORM django (ví dụ: 'chọn cột riêng1 từ tablename').django - hướng dẫn sử dụng ORM cho người dùng SQL?

Có tài liệu nào hiển thị "Đối với các câu lệnh SQL phổ biến, dưới đây là cách bạn thực hiện trong django"?

(tôi đã thử google đầu tiên, nhưng một trong hai nó không phải là ngoài kia hoặc tôi chỉ không thể nghĩ ra các truy vấn ngay ...)

Trả lời

8

Có một số điều vô cùng đơn giản trong SQL khó hoặc không thể thông qua ORM. Đây được gọi là "object-relational impedance mismatch". Về cơ bản, ORM xử lý từng hàng trong một cơ sở dữ liệu như một đối tượng riêng biệt. Vì vậy, các hoạt động liên quan đến việc xử lý các giá trị tách biệt khỏi hàng của chúng trở nên khá khó khăn. Các phiên bản gần đây của Django (1.1+) cải thiện tình trạng này một chút với aggregation support, nhưng đối với nhiều thứ, chỉ SQL sẽ hoạt động.

Để kết thúc này, django cung cấp một số phương pháp cho phép bạn thả xuống sql thô khá đơn giản. Một số người trong số họ trả về các đối tượng mô hình dưới dạng kết quả, trong khi một số khác đưa bạn đến tận trình kết nối DBAPI2 của bạn. Mức thấp nhất trông như thế này:

from django.db import connection 

cursor = connection.cursor() 
cursor.execute("SELECT DISTINCT column1 FROM tablename") 
row = cursor.fetchone() 

Nếu bạn muốn quay trở lại một queryset từ một truy vấn SQL, sử dụng nguyên liệu() trên người quản lý mô hình của bạn:

qs = ModelName.objects.raw("""SELECT first_name 
           FROM myapp_modelname 
           WHERE last_name = 'van Rossum'") 
for person in qs: 
    print person.first_name # Result already available 
    print person.last_name # Has to hit the DB again 

Lưu ý: thô () chỉ có sẵn trong phiên bản phát triển của Django, sẽ được hợp nhất thành thân cây là 1,2.

Thông tin đầy đủ có sẵn trong tài liệu theo số Performing raw SQL queries.

+0

Điều này đã làm cho tôi. Điểm mấu chốt là ORM trích xuất một tập hợp các đối tượng ("đối tượng" ~ = "toàn bộ hàng"), nhưng một hàng kết quả của SELECT DISTINCT không thể kết nối với một đối tượng đơn lẻ. Vì vậy, nếu bạn cần các đối tượng, hãy sử dụng ORM; nếu bạn cần một kết quả trong đó một hàng không thể được ánh xạ một cách đáng tin cậy vào một đối tượng duy nhất, hãy sử dụng SQL trực tiếp. Cảm ơn. – sienkiew

4

Một điểm khởi đầu tốt đẹp để làm Django truy vấn là các tài liệu Django chính họ.

http://docs.djangoproject.com/en/dev/topics/db/queries/

Dưới đây là một vài ví dụ:

select * from table 
= 
ModelName.objects.all() 

lọc:

select * from table where column = 'foo' 
= 
ModelName.objects.filter(column='foo') 

Cụ thể về việc sử dụng riêng biệt mà bạn sử dụng phương pháp riêng biệt() của một queryset Django.

Đây là liên kết có liên quan trong tài liệu. http://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct

Cập nhật: ORM giúp bạn bằng cách sử dụng tương tác hướng đối tượng với dữ liệu của bạn. Bạn không viết mã dịch kết quả truy vấn của bạn thành một tập hợp các đối tượng. Nó tự động. Đó là sự thay đổi cơ bản trong quá trình suy nghĩ mà bạn phải thực hiện.

Bạn bắt đầu nghĩ về 'Tôi có đối tượng này, tôi cần phải có được tất cả các đối tượng khác giống như' Sau đó, bạn có thể yêu cầu ORM cho các đối tượng đó. ORM, tôi cần tất cả các đối tượng của lớp sản phẩm đó có một thuộc tính của màu sắc "xanh" ngôn ngữ ORM cụ

Django cho rằng là:

products = Product.objects.filter(color='blue') 

này được thực hiện thay vì:

  • viết truy vấn sql của bạn,
  • thoát hoàn toàn tất cả đối số,
  • kết nối với cơ sở dữ liệu,
  • truy vấn cơ sở dữ liệu và xử lý các lỗi kết nối/truy vấn,
  • nhận kết quả,
  • lặp qua bộ kết quả dịch các giá trị trả về thành các đối tượng thích hợp mà bạn có thể gọi phương thức.

Đó là giá trị khi sử dụng ORM. Mã đơn giản hóa và giảm thời gian phát triển.

+0

Tất nhiên, tôi đọc tài liệu trước khi hỏi, mặc dù trong thế giới hiện đại, tôi có thể hiểu tại sao bạn có thể giả định khác. Vấn đề của tôi là tài liệu không trả lời câu hỏi của tôi một cách hiệu quả. Tôi không bao giờ tìm thấy RDBMS khó hiểu, và nó không phải là ở tất cả rõ ràng như thế nào ORM được coi là "giúp đỡ" tôi. Tôi đã hy vọng tìm thấy "Sách cụm từ của người du lịch: Django dành cho người nói SQL". – sienkiew

+0

Cập nhật câu trả lời của tôi cho bạn, tôi hy vọng điều này sẽ giúp giải thích quá trình suy nghĩ nhiều hơn. – wlashell

6

Hãy suy nghĩ theo cách này.

"Đối với các cuộc tấn công SQL phổ biến, thứ mà tôi định làm là gì?"

Vấn đề không phải là ORM phức tạp. Đó là bộ não của bạn đã bị biến dạng trong khuôn SQL, làm cho khó nhìn thấy các vật thể một cách rõ ràng.

Quy tắc chung:

  • Nếu bạn nghĩ rằng đó là một đơn giản CHỌN TỪ ĐÂU, dừng lại. Hỏi các đối tượng bạn cần xem trong tập kết quả. Sau đó, tìm các đối tượng đó và làm việc với trình quản lý đối tượng.

  • Nếu bạn nghĩ đơn giản là THAM GIA, hãy dừng lại. Hỏi đối tượng chính bạn muốn. Hãy nhớ rằng, các đối tượng không sử dụng các khóa ngoại. Tham gia không có ý nghĩa gì cả. Một đối tượng dường như phá vỡ 1NF và chứa và toàn bộ các đối tượng liên quan bên trong nó. Sau đó tìm các đối tượng "chính" và làm việc với trình quản lý đối tượng. Sử dụng các truy vấn đối tượng liên quan để tìm các đối tượng liên quan.

  • Nếu bạn cho rằng đó là OUTER JOIN, hãy dừng lại. Hỏi hai điều bạn muốn xem trong tập kết quả. Tham gia bên ngoài là những thứ sẽ tham gia UNIONED với những thứ sẽ không tham gia. Những thứ gì ở nơi đầu tiên. Sau đó tìm các đối tượng "chính" và làm việc với trình quản lý đối tượng. Một số sẽ có bộ các đối tượng liên quan. Một số thì không.

  • Nếu bạn cho rằng đó là WHERE EXISTS hoặc WHERE IN with subquery, mô hình của bạn có thể chưa hoàn chỉnh. Đôi khi, nó đòi hỏi một tham gia ưa thích. Nhưng nếu bạn đang thực hiện loại kiểm tra này, điều đó thường có nghĩa là bạn cần một tài sản trong mô hình của mình.

  • Nếu bạn nghĩ mình cần CHỌN CHỌN, bạn đã bỏ lỡ toàn bộ thuyền. Đó chỉ là một bộ Python. Bạn chỉ cần lấy các giá trị cột vào một bộ Python. Đó là những giá trị khác biệt.

  • Nếu bạn cho rằng mình cần GROUP BY, bạn sẽ bỏ qua Python collections.defaultdict. Sử dụng Python để GROUP BY thường nhanh hơn fussing xung quanh với SQL.

    Trừ kho dữ liệu. Mà bạn không nên làm ở Django. Bạn phải sử dụng SQLAlchemy cho kho dữ liệu.

2

Đối cụ thể của bạn như thế nào-to, bạn muốn làm điều đó như thế này:

MyModel.objects.values_list('column1', flat=True).distinct() 

Nhưng áp phích khác là chính xác để nói rằng bạn không nên suy nghĩ 'làm thế nào để viết SQL này trong ORM '. Khi bạn học Python, đến từ Java hoặc C++ hoặc bất cứ điều gì, bạn sớm học được cách suy nghĩ về 'làm cách nào để viết mã Java này bằng Python', và chỉ tập trung vào giải quyết vấn đề bằng Python. Điều này cũng đúng với việc sử dụng ORM.

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