2017-07-16 43 views
0

考慮下面的數據庫模型:Django的 - 過濾掉已評價的餐廳在喊叫像應用

class User: 
    id   = models.BigAutoField(primary_key=True) 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 

class Restaurant: 
    id = models.BigAutoField(primary_key=True) 
    title = models.CharField(max_length=50) 

class Rating: 
    id    = models.BigAutoField(primary_key=True) 
    by_user  = models.ForeignKey(to='User', 
             on_delete=models.PROTECT, 
             related_name='written_ratings') 
    for_restaurant = models.ForeignKey(to='Restaurant', 
             on_delete=models.PROTECT, 
             related_name='received_ratings') 
    score   = models.SmallIntegerField() 

    # make sure only one vote per user per restaurant 
    class Meta: 
     unique_together = ('by_user', 'for_restaurant') 

對於一個給定User,我們可以得到的Restaurant列表,我們還沒有通過執行以下查詢額定(我從my last post教訓)

eligible_restaurants = Restaurant.objects.exclude(rating__by_user_id=my_id) 

但當Ratings不會在Restaurants直接指向發生了什麼 - 而是在中間Profile對象?

class User: 
    id   = models.BigAutoField(primary_key=True) 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 

class Restaurant: 
    id    = models.BigAutoField(primary_key=True) 
    title   = models.CharField(max_length=50) 
    current_profile = models.OneToOneField(to='Profile', 
              on_delete=models.PROTECT, 
              related_name='+') 
    # the `+` means to not generate a related name 

class Profile: 
    # this is here acting as an intermediate between 
    # `Restaurant` and `Rating` so that we can keep track 
    # of all reviews - deleting/remaking would simply be 
    # creating a new `Profile` and setting the `Restaurant` 
    # to point to it instead - the old one will act as a 
    # historical record 
    id   = models.BigAutoField(primary_key=True) 
    by_restaurant = models.ForeignKey(to='Restaurant', 
             on_delete=models.PROTECT, 
             related_name='written_profiles') 
    picture_url = models.CharField(max_length=500) 
    picture_desc = models.CharField(max_length=500) 

class Rating: 
    id    = models.BigAutoField(primary_key=True) 
    by_user  = models.ForeignKey(to='User', 
             on_delete=models.PROTECT, 
             related_name='written_ratings') 
    for_profile = models.ForeignKey(to='Profile', 
             on_delete=models.PROTECT, 
             related_name='received_ratings') 
    score   = models.SmallIntegerField() 

    # make sure only one vote per user per restaurant 
    class Meta: 
     unique_together = ('by_user', 'for_profile') 

我現在將如何查詢符合條件的餐廳?

+0

您查詢配置文件並從中獲取餐廳。順便說一下,你的類必須從Model繼承。 –

回答

1

你可以過濾它們先從餐館

restaurant_ids = Rating.objects.filter(by_user=user).values_list('for_profile__by_restaurant', flat=True).distinct() 
eligible_restaurants = Restaurant.objects.exclude(id__in=restaurant_ids) 

注意:因爲Django的查詢集懶惰,這將產生只有一個查詢。

+0

嘿謝謝你的回覆。作爲django的新手 - 你有關於MySQL /數據庫django基準測試的建議嗎?當數據集變大(〜100k)時,有哪些方便的工具可以幫助我測試這些查詢的速度? – AlanSTACK

+0

@Alan我建議使用https://github.com/jazzband/django-debug-toolbar作爲初學者,那麼它真的取決於你想要做什麼樣的分析。 –