【问题标题】:Foreign key filter in a child object子对象中的外键过滤器
【发布时间】:2022-11-22 11:40:12
【问题描述】:

我有模型:


class Boss(models.Model):
    fullname = models.TextField()

class Shop(models.Model):
    name = models.TextField()
    address = models.TextField()
    phone = models.TextField()
    boss = models.ForeignKey(
        Boss, on_delete=models.CASCADE, related_name="shops"
    )

class Employee(models.Model):
    name = models.TextField()
    phone = models.TextField()
    shop = models.ForeignKey(
        Shop, on_delete=models.CASCADE, related_name="employees"
    )
class WorkSpace(models.Model):
    name = models.TextField()
    employee = models.ForeignKey(
        Shop, on_delete=models.CASCADE, related_name="work_spaces"
    )

序列化程序:

class WorkSpaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = WorkSpace
        fields = ["id","type"]

class EmployeeSerializer(serializers.ModelSerializer):
    work_spaces = WorkSpaceSerializer(many=True, read_only=True)

    class Meta:
        model = Employee
        fields = ["id","work_spaces","name","phone"]

class ShopSerializer(serializers.ModelSerializer):
    employees = EmployeeSerializer(many=True, read_only=True)

    class Meta:
        model = Shop
        fields = ["id","employees","phone","name","address"]

class BossSerializer(serializers.ModelSerializer):
    shops = ShopSerializer(many=True, read_only=True)

    class Meta:
        model = Boss
        fields = ["id","fullname","shops"]

看法

class BossListView(
    ListModelMixin,
    GenericViewSet,
):
    
    queryset = Boss.objects.all()
    serializer_class = BossSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        workspace_type = self.request.query_params.get("workspace_type")
        qs = super().get_queryset()
        if workspace_type:
            qs = qs.filter(shops__employees__work_spaces__type=workspace_type.lower()).distinct()
        return qs

我过滤了 Boss.objects.filter(shops__employees__work_spaces__type=C1) 并得到:

{
    "shops": [
        {
            "id": 32,
            "name": "Garden flowers",
            "address": "5 st. Hool-Maa",
            "phone": "879124851861598",
            "employees": [
                {
                    "id": 150,
                    "name": "Mike",
                    "phone": "8154451246",
                    "work_spaces": [
                        {
                            "id": 497,
                            "type": "B12"
                        },
                        {
                            "id": 15,
                            "type": "Z5"
                        },
                        {
                            "id": 33,
                            "type": "C1"
                        }
                    ]
                }
            ]
        }
    ]
}

但我只需要来自 work_spaces 的 C1:

                [{
                  "id": 33,
                  "type": "C1"
                }]

我怎样才能排除其他工作空间来自查询集还是我需要将结果转换为列表然后使用 for 循环进行过滤?可以有很多工作区,我不需要将它们全部显示给用户,我需要有关老板、商店、员工的信息。

【问题讨论】:

  • 请也添加您的序列化程序
  • 您能否也分享一下您的看法?
  • @IainShelvington 添加
  • @lbris 添加视图

标签: sql django filter django-rest-framework django-queryset


【解决方案1】:

您可以尝试使用 C1 周围的引号吗?

像这样 :

Boss.objects.filter(shops__employees__work_spaces__type="C1")

否则,您可以分享您的 type 字段的定义吗?

此外,但这只是我的意见,用 built-in 函数的名称来命名属性是个坏主意。在这里,我不会使用“类型”这个词来命名这个属性。

【讨论】:

  • 我在 API 中使用它,“C1”(或任何其他过滤器)来自用户。类型只是关于商店空间的信息,没有什么特别的,就像国际象棋一样。
  • 我用最少的细节重新创建了问题,所以类型有不同的名称,不要关注它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多