Django反向外键导致重复查询

Django reverse foreign key leading to duplicate queries

我正在尝试使用 ViewSet return 列出具有资产类型名称(而不仅仅是 id)的所有资产,但根据 django-debug-toolbar,我的查询被重复导致速度变慢结果。

1 资产类型可以有多个资产。

因此,当我尝试检索所有资产时 (children) -- 它正在尝试获取每个资产的资产类型 (parent) 名称 (child ren) 但它是 运行 每个资产的一个查询 (child)。看起来像这样:它被复制了 6 次,因为我目前在资产 table 中有 6 个值。

QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.00    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.95    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.

预期输出

我想要的只是所有资产的列表以及 AssetType 名称——有更好的方法吗?

这是我的模型:

class AssetType(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=80, unique=True)
    description = models.CharField(max_length=80)
    
    class Meta:
        db_table = "mm_asset_type"

class Asset(models.Model):
    asset_type = models.ForeignKey(AssetType, on_delete=models.CASCADE)
    asset_name = models.CharField(max_length=80)
    display_name = models.CharField(max_length=80)

    class Meta:
        db_table = "mm_asset_registry"

这是我的序列化程序:

class AssetTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = AssetType
        fields = "__all__"


class AssetSerializer(serializers.ModelSerializer):
    asset_type_name = serializers.CharField(source='asset_type.name')
    
    class Meta:
        model = Asset
        fields = ("id", "asset_type_name", "asset_name", "display_name")  

最后,这是我的 ViewSet

class AssetViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    queryset = Asset.objects.all()
    serializer_class = AssetSerializer

因此,当我尝试检索所有资产时 -- 它试图获取每项资产的资产类型名称,但它是 运行 对每项资产的一个查询。看起来像这样:

QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.00    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.95    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.

预期输出

我想要的只是所有资产 (children) 以及资产类型 (parent) 名称的列表 -- 有更好的方法吗?

谢谢

您应该使用 .select_related(…) [Django-doc] 来获取具有相同查询的类型:

class AssetViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    queryset = Asset.objects<strong>.select_related('asset_type')</strong>
    serializer_class = AssetSerializer

因此,这也会在与获取 Asset 的查询相同的查询中获取 asset_type 字段,从而将查询总数减少到一个。