Python Django-在yelp-like应用程序中过滤出已经评级的餐厅

Python Django-在yelp-like应用程序中过滤出已经评级的餐厅,python,django,django-models,Python,Django,Django Models,考虑以下数据库模型: 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) t

考虑以下数据库模型:

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')
对于给定的用户,我们可以通过执行我从中了解到的以下查询来获得尚未评级的餐厅列表

但是,如果评级不是直接指向餐厅,而是指向中间轮廓对象,会发生什么呢


我现在如何查询符合条件的餐厅?

您可以从餐厅开始筛选

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的查询集是惰性的。

您可以查询配置文件并从中获取餐厅。顺便说一句,你的类必须从模型继承。嘿,谢谢你的回复。作为django的新手,您对MySQL/数据库django基准测试有什么建议吗?当数据集变大~100k时,是否有任何方便的工具可以帮助我测试这些查询的速度?@Alan我建议初学者使用这些工具,然后这取决于您试图进行的评测。
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')
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)