[ Django Orm ManyToMany字段查询 ]


背景介绍

查询同时拥有workgroup_id=1, workgroup_id=2的用户

模型

class User(AbstractUser):
    """
    Default custom user model for backend.
    If adding fields that need to be filled at user signup,
    check forms.SignupForm and forms.SocialSignupForms accordingly.
    """

    class RoleType(TextChoices):
        TESTER = "Tester"
        CHECKER = "Checker"
        ENDORSER = "Endorser"

    staffNo = CharField(max_length=255, default="")
    name = CharField(_("Name of User"), blank=True, max_length=255)
    enable_email = models.BooleanField(default=True)
    work_groups =  models.ManyToManyField("cews.Workgroup" ,blank=True, default=None)

orm代码

        query = Q()
        query1 = Q()

        if work_group:
            work_group_obj = Workgroup.objects.get(workgroup=work_group)
            query &= Q(work_groups=work_group_obj)
        if sub_work_group:
            sub_work_group_obj = Workgroup.objects.get(workgroup=sub_work_group)
            query1 &= Q(work_groups=sub_work_group_obj)

SQL预计语句

SELECT u.*
FROM users_user u
INNER JOIN users_user_work_groups wg1 ON u.id = wg1.user_id AND wg1.workgroup_id = 1
INNER JOIN users_user_work_groups wg2 ON u.id = wg2.user_id AND wg2.workgroup_id = 5

# 在django中对应的语句
SELECT *
FROM "users_user" 
INNER JOIN "users_user_work_groups" ON ("users_user"."id" = "users_user_work_groups"."user_id") 
INNER JOIN "users_user_work_groups" T4 ON ("users_user"."id" = T4."user_id") 
WHERE ("users_user_work_groups"."workgroup_id" = 1 AND T4."workgroup_id" = 9)

总结

  1. 需要使用两个filter来触发两个join