2012-04-03 23 views
6

Tôi gặp sự cố khi nhận truy vấn ORM Django để hoạt động chính xác. Tôi có mô hình Hữu nghị này:Truy vấn ORM Django cho bạn bè của một người dùng

class Friendship(models.Model): 
    user1 = models.ForeignKey(User, related_name='friendships1') 
    user2 = models.ForeignKey(User, related_name='friendships2') 
    class Meta: 
     unique_together = ('user1', 'user2',) 

Để tìm những người bạn cho một người dùng nhất định, chúng ta phải kiểm tra user1 và user2 bởi vì chúng tôi không bao giờ có thể chắc chắn những gì bên trong những mối quan hệ họ sẽ về. Vì vậy, để có được tất cả bạn bè cho một người dùng nhất định, tôi sử dụng truy vấn sau:

user = request.user 
User.objects.filter(
    Q(friendships1__user2=user, friendships1__status__in=statuses) | 
    Q(friendships2__user1=user, friendships2__status__in=statuses) 
) 

Điều này dường như tôi thích nó sẽ hoạt động, nhưng không. Nó mang lại cho tôi bản sao. Dưới đây là SQL mà nó tạo ra:

SELECT auth_user.* 
FROM auth_user 
LEFT OUTER JOIN profile_friendship ON (auth_user.id = profile_friendship.user1_id) 
LEFT OUTER JOIN profile_friendship T4 ON (auth_user.id = T4.user2_id) 
WHERE (
    (profile_friendship.status IN ('Accepted') AND profile_friendship.user2_id = 1) 
    OR (T4.user1_id = 1 AND T4.status IN ('Accepted')) 
); 

đây là SQL mà tôi muốn, mà tạo ra kết quả chính xác:

SELECT f1.id as f1id, f2.id AS f2id, u.* 
FROM auth_user u 
LEFT OUTER JOIN profile_friendship f1 ON (u.id = f1.user1_id AND f1.user2_id = 1 AND f1.status IN ('Accepted')) 
LEFT OUTER JOIN profile_friendship f2 ON (u.id = f2.user2_id AND f2.user1_id = 1 AND f2.status IN ('Accepted')) 
WHERE f1.id IS NOT NULL OR f2.id IS NOT NULL 

Tôi biết tôi có thể làm điều này trong một truy vấn liệu, nhưng sau đó tôi don Tôi nghĩ rằng tôi sẽ có thể chuỗi. Có cách nào tốt đẹp sạch để làm điều này mà không đi nguyên?

Trả lời

1

Giải pháp đơn giản:

user = request.user 
User.objects.filter(
    Q(friendships1__user2=user, friendships1__status__in=statuses) | 
    Q(friendships2__user1=user, friendships2__status__in=statuses) 
).distinct() 

Bất cứ ai biết bất cứ nhược điểm?

+0

Tôi đã thử nghiệm điều này và nó hoạt động. Cá nhân tôi sẽ không viết truy vấn chính xác như ORM đang nhổ nó ra, nhưng nó vẫn có vẻ hoạt động khá tốt. Nhược điểm duy nhất ở đây là các bản sao có thể có bằng cách sử dụng một trường theo thứ tự mà không được bao gồm trong tập kết quả. – Dustin

3
+0

Anh ấy cần lưu trữ thêm thông tin, có vẻ như nó sẽ không hoạt động. – santiagobasulto

+0

@santiagobasulto hoặc chỉ định [qua bảng] (https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany) cho M2M –

+0

Giải pháp từ giải pháp @santiagobasulto hoạt động cho tôi. Tuy nhiên, tôi tự hỏi nếu giải pháp này có thể đơn giản hơn một chút và thậm chí có thể làm việc tốt hơn, miễn là tôi vẫn có thể chỉ định một bảng thông qua. Tuy nhiên, nó không rõ ràng với tôi làm thế nào để làm điều đó trong một mối quan hệ đối xứng. Tôi đang cố gắng tìm ra điều đó ngay bây giờ ... – Dustin

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