使用 django-taggit 获取与父对象关联的所有标签
Getting all the tags associated with the parent object using django-taggit
我有模型 Restaurant
和 Review
。 Review
有 TaggableManager()
我没问题让标签用于评论。但我也想知道与 Restaurant
对象关联的所有标签。
我可以编写自己的函数来循环访问餐厅的所有评论,以获取与餐厅关联的所有标签。但我正在寻找更简洁、更简单的方法来获取在单个数据库查询中完成它的标签。
我认为在单个查询中不可能,但此解决方案需要五个数据库查询:
# 1 query: Get restaurant
restaurant = Restaurant.objects.get(pk=pk)
# 2 query: Get content type of restaurant model
restaurant_ct = ContentType.objects.get_for_model(restaurant)
# 3 query: Get all reviews ids for a restaurant
reviews_ids = Review.objects.filter(content_type__id=restaurant_ct.id, object_id=restaurant.id).values_list('id', flat=True)
# 4 query: Get content type of review model
review_ct = ContentType.objects.get(app_label='review', model='review')
# 5 query: Get all tags
tags = TaggedItem.objects.filter(object_id__in=reviews_ids, content_type__id=review_ct.id)
但请注意,__in
对评论 ID 的查找可能会在 TaggedItem
上变得昂贵。但是您想要最少的数据库查询。
您可以通过在单个查询中获取餐厅和评论模型这两种内容类型来减少更多查询,但这不是一种优雅的方式:
ctypes = ContentType.objects.filter(
app_label__in=['review', 'restaurant'],
model__in=['review', 'restaurant']
)
assert len(ctypes) is 2
if ctypes[0].model == 'restaurant':
restaurant_ct = ctypes[0]
review_ct = ctypes[1]
else:
review_ct = ctypes[0]
restaurant_ct = ctypes[1]
我有模型 Restaurant
和 Review
。 Review
有 TaggableManager()
我没问题让标签用于评论。但我也想知道与 Restaurant
对象关联的所有标签。
我可以编写自己的函数来循环访问餐厅的所有评论,以获取与餐厅关联的所有标签。但我正在寻找更简洁、更简单的方法来获取在单个数据库查询中完成它的标签。
我认为在单个查询中不可能,但此解决方案需要五个数据库查询:
# 1 query: Get restaurant
restaurant = Restaurant.objects.get(pk=pk)
# 2 query: Get content type of restaurant model
restaurant_ct = ContentType.objects.get_for_model(restaurant)
# 3 query: Get all reviews ids for a restaurant
reviews_ids = Review.objects.filter(content_type__id=restaurant_ct.id, object_id=restaurant.id).values_list('id', flat=True)
# 4 query: Get content type of review model
review_ct = ContentType.objects.get(app_label='review', model='review')
# 5 query: Get all tags
tags = TaggedItem.objects.filter(object_id__in=reviews_ids, content_type__id=review_ct.id)
但请注意,__in
对评论 ID 的查找可能会在 TaggedItem
上变得昂贵。但是您想要最少的数据库查询。
您可以通过在单个查询中获取餐厅和评论模型这两种内容类型来减少更多查询,但这不是一种优雅的方式:
ctypes = ContentType.objects.filter(
app_label__in=['review', 'restaurant'],
model__in=['review', 'restaurant']
)
assert len(ctypes) is 2
if ctypes[0].model == 'restaurant':
restaurant_ct = ctypes[0]
review_ct = ctypes[1]
else:
review_ct = ctypes[0]
restaurant_ct = ctypes[1]