2012-10-01 31 views
8

Tôi xin lỗi nếu câu hỏi của tôi hóa ra là ngớ ngẩn, nhưng tôi khá mới với Django, và tôi không thể tìm thấy câu trả lời ở bất cứ đâu.Mô hình Django - chỉ định id thay vì đối tượng

tôi có mô hình sau:

class BlackListEntry(models.Model): 
    user_banned = models.ForeignKey(auth.models.User,related_name="user_banned") 
    user_banning = models.ForeignKey(auth.models.User,related_name="user_banning") 

Bây giờ, khi tôi cố gắng để tạo ra một đối tượng như thế này:

BlackListEntry.objects.create(user_banned=int(user_id),user_banning=int(banning_id)) 

tôi nhận được một lỗi sau:

Cannot assign "1": "BlackListEntry.user_banned" must be a "User" instance. 

Trong số Tất nhiên, nếu tôi thay thế nó bằng một cái gì đó như thế này:

user_banned = User.objects.get(pk=user_id) 
user_banning = User.objects.get(pk=banning_id) 
BlackListEntry.objects.create(user_banned=user_banned,user_banning=user_banning) 

mọi thứ hoạt động tốt. Câu hỏi là:

Giải pháp của tôi có nhấn vào cơ sở dữ liệu để truy xuất cả người dùng hay không và nếu có, có thể tránh nó không, chỉ cần chuyển id?

Trả lời

10

Câu trả lời cho câu hỏi của bạn là: CÓ.

Django sẽ nhấn vào cơ sở dữ liệu (ít nhất) 3 lần, 2 để truy xuất hai đối tượng Người dùng và một đối tượng thứ ba để cam kết thông tin mong muốn của bạn. Điều này sẽ gây ra một chi phí không cần thiết.

Chỉ cần cố gắng:

BlackListEntry.objects.create(user_banned_id=int(user_id),user_banning_id=int(banning_id)) 

Những là mô hình tên mặc định cho các lĩnh vực FK được tạo ra bởi Django ORM. Bằng cách này bạn có thể đặt thông tin trực tiếp và tránh các truy vấn.

Nếu bạn muốn truy vấn cho các đối tượng BlackListEntry đã lưu, bạn có thể điều hướng các thuộc tính với một dấu gạch dưới đôi, như thế này:

BlackListEntry.objects.filter(user_banned__id=int(user_id),user_banning__id=int(banning_id)) 

Đây là cách bạn truy cập vào các thuộc tính trong queryset Django. với dấu gạch dưới kép. Sau đó, bạn có thể so sánh với giá trị của thuộc tính.

Mặc dù rất giống nhau, chúng hoạt động hoàn toàn khác nhau. Việc đầu tiên đặt một thuộc tính trực tiếp trong khi một thứ hai được phân tích cú pháp bởi django, mà tách nó tại '__', và truy vấn cơ sở dữ liệu đúng cách, là phần thứ hai tên của một thuộc tính.

Bạn luôn có thể so sánh user_banneduser_banning với các đối tượng Người dùng thực tế thay vì id của chúng. Nhưng không có sử dụng cho điều này nếu bạn không có những đối tượng với bạn.

Hy vọng điều đó sẽ hữu ích.

+0

Điều này cho tôi: 'user_banning__id' là đối số từ khóa không hợp lệ cho hàm này –

+0

Tôi rất tiếc, tôi vừa mới nhận ra bạn đang tạo đối tượng. Vì vậy, bạn cần truy cập bằng một dấu gạch dưới đơn. Tôi sẽ chỉnh sửa câu trả lời của mình để giải thích tại sao. – Francisco

+0

Cảm ơn, bây giờ nó hoạt động. Tôi sẽ thêm bạn +1, nhưng tôi quá n00bly để làm điều đó được nêu ra. –

0

Tôi tin rằng khi bạn lấy những người sử dụng, nó sẽ nhấn db ...

Để tránh nó, bạn sẽ phải viết sql liệu để làm các cập nhật bằng phương pháp mô tả ở đây:

https://docs.djangoproject.com/en/dev/topics/db/sql/

Nếu bạn quyết định đi tuyến đường đó, hãy nhớ rằng bạn có trách nhiệm tự bảo vệ mình khỏi các cuộc tấn công phun sql.

Một giải pháp thay thế khác là lưu vào bộ nhớ cache đối tượng user_banned và user_banning.

Nhưng trong mọi khả năng, chỉ cần lấy người dùng và tạo BlackListEntry sẽ không gây ra cho bạn bất kỳ vấn đề hiệu suất đáng chú ý nào. Caching hoặc thực thi sql thô sẽ chỉ cung cấp một lợi ích nhỏ. Có thể bạn sẽ gặp phải các vấn đề khác trước khi vấn đề này trở thành vấn đề.

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