如何使用django序列化程序获取对象包含Foreignkey id而不执行对每个引用对象

时间:2017-03-18 14:21:59

标签: django django-views django-serializer

我是Django的新手,但在我们的项目中我们有一个Django后端,没有其他人愿意接触它,所以我不得不对此进行一些调整。模型设置,一切正常,但我们需要一个新视图,我们需要有关我们的一个模型的基本数据,没有引用模型(只需要外键ID)。我之前已经有了SO的解决方案,但是当该解决方案返回首选结果时,仍然会在后台执行大量查询。每个返回的对象都会查询每个引用的对象,同时我们只需要它们的id /键。

与此同时,我已将序列化器修改为trinchet,但这并没有帮助。仍然有很多疑问。

型号:

class Row(models.Model):
    row = models.IntegerField(null=True, blank=True)
    height = models.TextField(null=True, blank=True)
    key = models.CharField(max_length=36, unique = True)

    def save(self, *args, **kwargs):
        super(Row, self).save(*args, **kwargs)


class Column(models.Model):
    col = models.IntegerField(null=True, blank=True)
    width = models.TextField(null=True, blank=True)

    key = models.CharField(max_length=36, unique = True)

    def save(self, *args, **kwargs):
        super(Column, self).save(*args, **kwargs)


class Product(models.Model):

    key = models.CharField(max_length=36, unique = True)

    text = models.TextField(null=True, blank=True)

    column = models.ForeignKey(Column, db_column='column_key', to_field='key', related_name="products")
    row  = models.ForeignKey(Row, db_column='row_key', to_field='key', related_name="products")
    merged_with = models.ForeignKey("Product", db_column='merged_with_key', to_field='key', related_name="merges", blank=True, null=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    updated_by = models.ForeignKey('auth.User', null=True)

串行:

class SimpleProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('id', 'key', 'text', 'row', 'column', 'merged_with')

    row = serializers.PrimaryKeyRelatedField(read_only = True)
    column = serializers.PrimaryKeyRelatedField(read_only = True)
    merged_with = serializers.PrimaryKeyRelatedField(read_only = True)

结果是一个简单的json,它包含纯产品对象数组:

[{
    id: 1,
    key: "1746495d-8ea0-42df-9ed9-06df621ef7c5",
    column_key: "<key of refrenced column>"
    key: "1746495d-8ea0-42df-9ed9-06df621ef7c5"
    merged_with_key: "<key of refrenced product>"
    row_key: "<key of refrenced row>"
    text: "sometext"
}, .....]

但是在后端,已经执行了大量查询来检索每个产品对象的列/行。

DEBUG 2017-03-18 11:27:27,704 utils 424 140142129104640 (0.001) SELECT "dashboard_product"."id", "dashboard_product"."dashboard_id", "dashboard_product".
"key", "dashboard_product"."text", "dashboard_product"."column_key", "dashboard_produc
t"."row_key", "dashboard_product"."merged_with_key" FROM "dashboard_product" WHERE "dashboard_product"."key" IN ('2a578e00-af19-4b3d-a
65f-5bf9daf490f7', '29c571bc-fb58-42b6-8721-edb8a96cc682', '6fb9ed7a-0e4f-4c06-95d3-15f16d281247', 'b6aa4aa3-be47-4641-a79b-1eddc3e4d28d', '026ea99a-75cd
-4708-adbd-117aef19a159', '86f49c57-1ba4-4b63-aadb-01eb95984306', 'f4a2f175-afa2-4337-891a-fce15ceaab1b', 'c31f2244-3e44-4c7e-b68a-997a0c25426f', 'cb2656
c3-7515-443a-8217-45e8a4e32d42', NULL, 'a801e609-49a2-46bb-9fad-453e9ebc6143', '2e2c85ae-bd60-43ae-9b6c-00988e69d470', '54165d95-ced7-4e28-b6e8-6c604f094
808', '74bda05f-5bf3-47ec-bbb0-b16eaf1839ec'); args=('2a578e00-af19-4b3d-a65f-5bf9daf490f7', '29c571bc-fb58-42b6-8721-edb8a96cc682', '6fb9ed7a-0e4f-4c06-
95d3-15f16d281247', 'b6aa4aa3-be47-4641-a79b-1eddc3e4d28d', '026ea99a-75cd-4708-adbd-117aef19a159', '86f49c57-1ba4-4b63-aadb-01eb95984306', 'f4a2f175-afa
2-4337-891a-fce15ceaab1b', 'c31f2244-3e44-4c7e-b68a-997a0c25426f', 'cb2656c3-7515-443a-8217-45e8a4e32d42', None, 'a801e609-49a2-46bb-9fad-453e9ebc6143',
'2e2c85ae-bd60-43ae-9b6c-00988e69d470', '54165d95-ced7-4e28-b6e8-6c604f094808', '74bda05f-5bf3-47ec-bbb0-b16eaf1839ec')

DEBUG 2017-03-18 11:27:27,712 utils 424 140142129104640 (0.001) SELECT "dashboard_row"."id", "dashboard_row"."dashboard_id", "dashboard_row"."row", "dash
board_row"."height", "dashboard_row"."key" FROM "dashboard_row" WHERE "dashboard_row"."key" = '905bd277-3a31-4361-8877-dc3c019aff29'; args=('905bd277-3a3
1-4361-8877-dc3c019aff29',)

DEBUG 2017-03-18 11:27:27,717 utils 424 140142129104640 (0.001) SELECT "dashboard_column"."id", "dashboard_column"."dashboard_id", "dashboard_column"."co
l", "dashboard_column"."width", "dashboard_column"."key" FROM "dashboard_column" WHERE "dashboard_column"."key" = '4633a6a0-4532-4681-851e-562c1e409b15';
 args=('4633a6a0-4532-4681-851e-562c1e409b15',)

DEBUG 2017-03-18 11:27:27,720 utils 424 140142129104640 (0.000) SELECT "dashboard_row"."id", "dashboard_row"."dashboard_id", "dashboard_row"."row", "dash
board_row"."height", "dashboard_row"."key" FROM "dashboard_row" WHERE "dashboard_row"."key" = '905bd277-3a31-4361-8877-dc3c019aff29'; args=('905bd277-3a3
1-4361-8877-dc3c019aff29',)

DEBUG 2017-03-18 11:27:27,722 utils 424 140142129104640 (0.000) SELECT "dashboard_column"."id", "dashboard_column"."dashboard_id", "dashboard_column"."co
l", "dashboard_column"."width", "dashboard_column"."key" FROM "dashboard_column" WHERE "dashboard_column"."key" = 'e30ea177-3819-4b57-b725-6d89b207d740';
 args=('e30ea177-3819-4b57-b725-6d89b207d740',)

DEBUG 2017-03-18 11:27:27,724 utils 424 140142129104640 (0.000) SELECT "dashboard_row"."id", "dashboard_row"."dashboard_id", "dashboard_row"."row", "dash
board_row"."height", "dashboard_row"."key" FROM "dashboard_row" WHERE "dashboard_row"."key" = '6a5a9e1a-9098-430a-985a-81c61e29f3db'; args=('6a5a9e1a-909
8-430a-985a-81c61e29f3db',)
... etc

如何阻止此行为,仅执行一个返回产品对象的查询,并且不会触及我们不使用的引用。现在这是一个严重的性能瓶颈,我花了很长时间才找到解决方案。 我已经使用json序列化器解决了这个问题,但它们无法处理数组字段,还有一些其他问题。必须有一种更优雅的方式来解决这个问题。

BR,

乔鲍

1 个答案:

答案 0 :(得分:0)

你可以做几件事:

  1. 明确地在SimpleProductSerializer序列化程序中为每个ForeignKey定义PrimaryKeyRelatedField字段,或
  2. 在传递给SimpleProductSerializer
  3. 的查询集中使用select_related/prefetch_related

    它们都将消除不需要的查询,但在第二种情况下,您将获得一些您不需要的数据(在查询中)(整个相关对象而不仅仅是ID)