我有一个简单的模型,其中包含一个产品和类别表。 Product 模型有一个外键类别。
当我调用返回类别列表的 tastypie API 时/api/vi/categories/ 我想添加一个字段来确定“产品数量”/具有给定类别的产品数量。结果将类似于:
category_objects[
{
id: 53
name: Laptops
product_count: 7
},
...
]
以下代码可以正常工作,但对我的数据库的影响很大
def dehydrate(self, bundle):
category = Category.objects.get(pk=bundle.obj.id)
products = Product.objects.filter(category=category)
bundle.data['product_count'] = products.count()
return bundle
是否有更有效的方法来构建此查询?也许用注释?
请您参考如下方法:
您可以使用 prefetch_related QuerSet 的方法来反转 select_related。
Asper 文档,
prefetch_related(*lookups)
Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.
This has a similar purpose to select_related, in that both are designed to stop the deluge of database queries that is caused by accessing related objects, but the strategy is quite different.
如果将脱水函数更改为以下,则数据库将被命中一次。
def dehydrate(self, bundle):
category = Category.objects.prefetch_related("product_set").get(pk=bundle.obj.id)
bundle.data['product_count'] = category.product_set.count()
return bundle
更新 1
您不应该在 dehydrate 函数中初始化查询集。 queryset 应始终仅在 Meta 类中设置。请查看 django-tastypie 文档中的以下示例。
class MyResource(ModelResource):
class Meta:
queryset = User.objects.all()
excludes = ['email', 'password', 'is_staff', 'is_superuser']
def dehydrate(self, bundle):
# If they're requesting their own record, add in their email address.
if bundle.request.user.pk == bundle.obj.pk:
# Note that there isn't an ``email`` field on the ``Resource``.
# By this time, it doesn't matter, as the built data will no
# longer be checked against the fields on the ``Resource``.
bundle.data['email'] = bundle.obj.email
return bundle
根据官方 django-tastypie documentation在 dehydrate() 函数上,
dehydrate
The dehydrate method takes a now fully-populated bundle.data & make any last alterations to it. This is useful for when a piece of data might depend on more than one field, if you want to shove in extra data that isn’t worth having its own field or if you want to dynamically remove things from the data to be returned.
dehydrate() 仅用于对 bundle.data 进行任何最后的更改。
