有关 drf 中一些关于嵌套关系的问题想请教 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mseasons
V2EX    Django

有关 drf 中一些关于嵌套关系的问题想请教

  •  
  •   mseasons 2018-12-03 08:35:08 +08:00 3681 次点击
    这是一个创建于 2534 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在些项目的时候遇到一个有关嵌套关系的 bug,想了一段时间,想到几种解决方案,但是不知道什么样子是最优的,来问问前辈们……

    问题描述:我用 drf 写的后端接口,在写序列化类的时候,遇到了嵌套关系的问题,比如我现在有一个一级类型一个二级类型,一级类型包含二级类型,在二级类型表中有一个一级类型的外键,删除操作用逻辑删除,将删除的那一行的 status 字段设置值为 1。

    这样单独请求哪个接口的时候都不会出问题。代码如下:

    class ProductPrimaryTypeViewSet(BaseViewSet): queryset = ProductPrimaryType.objects.filter(status=0) serializer_class = ProductPrimaryTypeSerializer class ProductSecondaryTypeViewSet(BaseViewSet): queryset = ProductSecondaryType.objects.filter(status=0) serializer_class = ProductSecondaryTypeSerializer 

    但是嵌套的时候就会出问题,我在一级类型的序列化类中添加了二级类型的嵌套,代码如下:

    class ProductSecondaryTypeSerializer(serializers.ModelSerializer): product_primary_type_name = serializers.SerializerMethodField() def get_product_primary_type_name(self, obj): return obj.product_primary_type.name class Meta: model = ProductSecondaryType fields = ('id', 'name', 'product_primary_type_id', 'product_primary_type_name') class ProductPrimaryTypeSerializer(serializers.ModelSerializer): product_secondary_types = ProductSecondaryTypeSerializer(many=True, source='productsecondarytype_set') class Meta: model = ProductPrimaryType fields = ('id', 'name', 'product_secondary_types') 

    这个时候直接访问二级类型的接口是可以直接过滤掉已经逻辑删除的行的,但是访问一级类型的接口的时候还是会显示已经删除的行,想问一下,怎么做筛选呢?

    我想了一些方法,但是不知道怎么做才是最优的,因为未来需求可能变,乱写可能改代码的时候很痛苦。所以来请教一下。

    方法 1 :重写二级类型序列化类的 to_representation 方法,在返回的时候如果 status=1 则直接返回 None,然后在一级类型序列化类的 to_representation 方法中过滤掉所有的 None。

    方法 2:创建一个没用的一级类型数据,然后让这个数据的 status=1 (逻辑删除),然后之后做逻辑删除的二级类型项的一级类型外键值都等于这个行,我倾向于这个……但是感觉很蠢。

    希望有前辈能帮我解答疑惑。

    9 条回复    2018-12-03 19:04:42 +08:00
    jimmyye
        1
    jimmyye  
       2018-12-03 09:10:32 +08:00
    “但是访问一级类型的接口的时候还是会显示已经删除的行”,说的是会显示已删除的二级类型吧?过滤应该在 queryset 中进行,可以在 prefetch 的时候用`Prefetch`过滤掉。
    https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.Prefetch
    https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related
    Outliver0
        2
    Outliver0  
       2018-12-03 09:12:53 +08:00
    在二级类型中过滤掉,你每次查询都要过滤掉逻辑删除的部分
    mseasons
        3
    mseasons  
    OP
       2018-12-03 09:14:29 +08:00
    @Outliver0 我知道…… 我的目标就是这个,但是不知道怎么去找到一个最好的方案。
    matrix1010
        4
    matrix1010  
       2018-12-03 09:25:28 +08:00 via Android
    接着用 SerializerMethodField,把 serializer 放里面。或者直接把 model 的 default manager 改了
    mseasons
        5
    mseasons  
    OP
       2018-12-03 09:32:55 +08:00
    @matrix1010 这个方法我也想过,可是如果存在外键很多的话,比如一级类型包含二级类型,其他的表有商品包含规格,等等,代码会很丑吗……
    matrix1010
        6
    matrix1010  
       2018-12-03 10:19:41 +08:00
    @mseasons 那就改 default manager 试试,这样改一个地方就行
    WilliamYang
        7
    WilliamYang  
       2018-12-03 11:03:12 +08:00
    matrix1010
        8
    matrix1010  
       2018-12-03 12:37:44 +08:00
    我刚才又看了看,related manager 不太容易 override,最简单的方法是给 model 加个 property,然后 serializer 的 source 写这个 property。这个在 model 里加比较好,因为 model 里有了其他地方都可以用
    mseasons
        9
    mseasons  
    OP
       2018-12-03 19:04:42 +08:00
    @matrix1010 SerializerMethodField 会导致多余查询很多次吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1207 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 23:38 PVG 07:38 LAX 15:38 JFK 18:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86