2012-02-17 30 views
12

Làm cách nào để tạo giả "chọn" thủ công để tránh các lần truy cập DB không mong muốn?Chọn liên quan đến Django trong yêu cầu thô

ta có:

class Country: 
    name = CharField() 
class City: 
    country = models.ForeignKey(Country) 
    name = models.CharField() 

cities = City.objects.raw("select * from city inner join country on city.country_id = country.id where name = 'london'") 

#this will hill hit DB 
print cities[0].country.name 

Làm thế nào để nói với django rằng các mô hình liên quan đã lấy.

+0

Bạn có thể thử sử dụng .values ​​() để truy lục các thành phố dưới dạng từ điển. Xem: https: //docs.djangoproject.com/en/dev/ref/models/querysets/#values ​​ – Jingo

Trả lời

1

Tôi không chắc chắn liệu bạn có thể thực hiện việc này hay không. Thay vào đó, bạn có thể chọn các trường riêng lẻ từ bảng quốc gia và truy cập chúng trên từng trường hợp.

cities = City.objects.raw("select city.*, name as country_name from city inner join country on city.country_id = country.id where name = 'london'") 

city = cities[0] 
# this will not hit the database again 
city.country_name 
+2

vâng, cách tiếp cận này sẽ hiệu quả, nhưng yêu cầu thiết kế lại mã hơn nữa. – Andrew

7

Một giải pháp với prefetch_related(điều này có nghĩa rằng hai truy vấn sẽ được thực hiện, 1 cho cities và 1 cho countries) lấy từ django-users mà không phải là một phần của API công cộng nhưng đang làm việc trên Django 1.7

from django.db.models.query import prefetch_related_objects 
#raw querysets do not have len() 
#thats why we need to evaluate them to list 
cities = list(City.objects.raw("select * from city inner join country on city.country_id = country.id where name = 'london'")) 
prefetch_related_objects(cities, ['country']) 

CẬP NHẬT

Bây giờ trong Django 1.10 prefetch_related_objects là một phần của API công khai.

6

Không chắc chắn nếu bạn vẫn cần điều này, nhưng tôi đã giải quyết nó bắt đầu bằng câu trả lời của Alasdair. Bạn muốn sử dụng thông tin từ truy vấn để xây dựng mô hình hoặc nó vẫn sẽ kích hoạt các truy vấn bổ sung khi bạn cố truy cập trường khóa ngoài. Vì vậy, trong trường hợp của bạn, bạn muốn:

cities = list(City.objects.raw(""" 
     SELECT 
      city.*, country.name as countryName 
     FROM 
      cities INNER JOIN country ON city.country_id = country.id 
     WHERE 
      city.name = 'LONDON""")) 
    for city in cities: 
     city.country = Country(name=city.countryName) 

Dòng chỉ định quốc gia không nhấn vào cơ sở dữ liệu, nó chỉ tạo mô hình. Sau đó, khi bạn truy cập city.country, nó sẽ không kích hoạt truy vấn cơ sở dữ liệu khác.

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