在Django中,我有两个模型:
class Product(models.Model):
name = models.CharField(max_length = 50)
categories = models.ManyToManyField(Category)
class ProductRank(models.Model):
product = models.ForeignKey(Product)
rank = models.IntegerField(default = 0)
我将排名放在一个单独的表中,因为页面的每个视图都会导致排名发生变化,我担心所有这些写入都会使我的其他(主要是读取)查询变慢。
我从一个简单的查询中收集Products
的列表:
cat = Category.objects.get(pk = 1)
products = Product.objects.filter(categories = cat)
我现在想要获得这些产品的所有排名。我更愿意一次性完成(使用SQL连接),并想知道如何使用Django的查询机制表达它。
在Django中执行此操作的正确方法是什么?
答案 0 :(得分:14)
这可以在Django中完成,但是您需要稍微改变一下您的模型:
class Product(models.Model):
name = models.CharField(max_length=50)
product_rank = models.OneToOneField('ProductRank')
class ProductRank(models.Model):
rank = models.IntegerField(default=0)
现在,在获取Product对象时,您可以使用select_related()方法在一个查询中遵循一对一关系:
Product.objects.filter([...]).select_related()
这将产生一个使用连接获取产品排名的查询:
SELECT "example_product"."id", "example_product"."name", "example_product"."product_rank_id", "example_productrank"."id", "example_productrank"."rank" FROM "example_product" INNER JOIN "example_productrank" ON ("example_product"."product_rank_id" = "example_productrank"."id")
我不得不将Product和ProductRank之间的关系字段移动到Product模型,因为它看起来像select_related()仅在一个方向上跟随外键。
答案 1 :(得分:4)
我还没检查过:
products = Product.objects.filter(categories__pk=1).select_related()
应抓住每个实例。
答案 2 :(得分:2)
添加一个对QuerySet的select_related()方法的调用,虽然我不是肯定的,它在两个方向上抓取引用,但这是最可能的答案。
答案 3 :(得分:1)
对于Django 2.1 来自文档
此示例检索名称为'Beatles Blog'的Blog的所有Entry对象:
Entry.objects.filter(blog__name='Beatles Blog')
文档网址 https://docs.djangoproject.com/en/2.1/topics/db/queries/