Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在Django中,如何保持多对多关系同步?_Python_Django_Django Models_Foreign Keys_Many To Many - Fatal编程技术网

Python 在Django中,如何保持多对多关系同步?

Python 在Django中,如何保持多对多关系同步?,python,django,django-models,foreign-keys,many-to-many,Python,Django,Django Models,Foreign Keys,Many To Many,在Django中,设置和更新多对多字段(缺少更好的术语)的最佳方法是什么?多对多字段是来自其他模型的多对多字段的组合 举一个具体的例子,我有一个代表简历的模型 class Resume(models.Model): owner = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="resume",

在Django中,设置和更新多对多字段(缺少更好的术语)的最佳方法是什么?多对多字段是来自其他模型的多对多字段的组合

举一个具体的例子,我有一个代表简历的模型

class Resume(models.Model):
    owner = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="resume",
    )
    description = models.TextField(default="Resume description")
    skills = models.ManyToManyField(Skill, related_name="resume")
Resume对象由另一个名为WorkExperience的模型引用:

class WorkExperience(models.Model):
    ...
    skills = models.ManyToManyField(Skill, related_name="work")
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=False,
        default=1,
        related_name="work_experience",
    )
    resume = models.ForeignKey(
        Resume,
        on_delete=models.CASCADE,
        null=False,
        default=1,
        related_name="work_experience",
    )
请注意,这里有相当多的冗余,简历和工作经验都指向同一个所有者等。也就是说,这两种模式(简历和工作经验)都有一个称为技能的领域。这参考了另一种叫做技能的模式

我想要的是简历中的技能,能够指出与工作经验中的技能相同的技能。有什么建议吗?我还有一个名为EducationExperience的模型,它也涉及技能,并且与简历有外键关系。有没有办法使简历中的技能与工作经验和教育经验中的技能保持同步

一个简单的选择是实现一个名为
set_resume_skills
的方法,当调用该方法时,该方法会将他们拥有的技能添加到resume拥有的技能列表中

Class WorkExperience(models.Model):
    # Same model as above
    def set_resume_skills(self):
        self.resume.skills.add(self.skills)
我对这种方法的问题是,它只增加了技能,并不能真正保持它们的同步。所以,如果我从工作经验中删除了一项技能,它就不会从简历中删除。另一个边界条件是,如果多个WorkExperience对象引用一项技能,然后我从一个对象中删除该技能,我如何确保简历中的引用仍然完整?即,两个工作经验对象引用技能“Javascript”。我从一个WorkExperience对象中移除该技能。技能“Javascript”仍然应该被简历引用,因为一个WorkExperience对象仍然有对它的引用


编辑:我想这样做的原因是为了减少前端的查询量。如果过滤技能的唯一方法是通过“子模型”(工作经验、教育经验),那么我需要在前端执行两个查询,而不是一个查询。虽然现在我想起来了,但做两个查询并没有那么糟糕。

我是从错误的角度来处理问题的。当我只是对技能对象进行反向查询时,我不必担心检查技能。目前,我正在筛选视图中的技能查询集,如下所示:

class SkillViewSet(viewsets.ModelViewSet):
    serializer_class = SkillSerializer

    def get_queryset(self):
        queryset = Skill.objects.all()
        email = self.request.query_params.get("email", None)
        if email:
            User = get_user_model()
            user = User.objects.get(email=email)
            query_work_experience = Q(work__owner=user)
            query_education_experience = Q(education__owner=user)
            queryset = queryset.filter(
                query_work_experience | query_education_experience
            )

        return queryset

这样就不需要将技能与简历模型保持同步。

根据您的设计,似乎技能实际上属于所有者,即授权用户。在简历和其他模型中有M2M关系肯定会导致冗余。为什么不在用户模型中创建一个M2M技能

关于减少查询,还有其他方法可以做到这一点。使用
select\u related
prefetch\u related

class User(models.Model):
skills = models.ManyToManyField(Skill, related_name="resume")
# ... Other fields here

class Resume(models.Model):
owner = models.OneToOneField(
    settings.AUTH_USER_MODEL,
    on_delete=models.CASCADE,
    related_name="resume",
)
description = models.TextField(default="Resume description")
# ... Other fields here

非常好,谢谢。我在直接指向AUTH_用户时一直没有必要犹豫,但这样做会显著降低复杂性。