【问题标题】:Django-ORM: Illustrate a precise query for the situationDjango-ORM:说明情况的精确查询
【发布时间】:2012-03-28 22:59:44
【问题描述】:

我的项目中有 4 个模型。分别是:

class Company(Group):

address_1 = models.CharField(max_length = 300, blank = True, null = True)
web_site = models.URLField(blank = True, null = True)
office_number = models.CharField(max_length = 20, blank = True, null = True)


class Person(models.Model):

user = models.ForeignKey(User)
company = models.ForeignKey(Company)


class Project(models.Model):

name = models.CharField(max_length = 100)
person = models.ManyToManyField(User, through = 'UserProject')


class UserProject(models.Model):

user = models.ForeignKey(User)
project = models.ForeignKey(Project)
is_owner = models.BooleanField(default = False)

在我想要得到的视图中

  1. 与request.user相关的所有项目
  2. 从事这些项目的公司
  3. 以及这些公司的员工

我尝试编写一些代码,但查询不准确。帮助将不胜感激!

【问题讨论】:

    标签: django python-2.7 django-orm


    【解决方案1】:

    我已经考虑并使用了上面列出的一些解决方案,但没有什么与我所寻找的完全一致。对我来说,下面这段代码效果很好

                projects = Project.objects.filter(person = request.user)
    
                user_projects = UserProject.objects.filter(project__in = projects)
    
                for user_project in user_projects:
                    person = user_project.user.get_profile()
                    company.append(person.company)
                    people.append(person)
    
                company = set(company)
    

    【讨论】:

      【解决方案2】:

      确定模型中的一些错误:

      • Project 通过 UserProject 在 User 上有一个 M2M,这很好,但我认为你的意思是它在 Person 上有一个对 User 有 FK 的 M2M
      • 其次,您尚未与公司建立任何关系。在修复该错误之前,您无法执行列表中的第 2 项。
      • 公司为什么要扩展集团?我一定是错过了什么。
      • 没有 Employee 模型

      例子:

      class Company(models.Model):
          address_1 = models.CharField(max_length = 300, blank = True, null = True)
          web_site = models.URLField(blank = True, null = True)
          office_number = models.CharField(max_length = 20, blank = True, null = True)
      
      
      class Employee(models.Model):
          user = models.ForeignKey(User)
          company = models.ForeignKey(User)
      
      
      class Project(models.Model):
          name = models.CharField(max_length = 100)
          employees = models.ManyToManyField(Employee, through = 'EmployeeProject')
          companies = models.ManyToManyField(Company)
      
      
      class EmployeeProject(models.Model):
      
          employee = models.ForeignKey(Employee)
          project = models.ForeignKey(Project)
          is_owner = models.BooleanField(default = False)
      

      在视图中

      # all of the projects for a user (assuming employee field is supposed to M2M to the Employee model
      projects = Project.objects.filter(employees__user=request.user)
      for project in projects :
          # assuming that there was some connection between project and company (there isnt currently, see me list of bugs with your models)
          for company in project.companies_set.all() :
              # There is no employee model, but if there was
              employees = company.employees_set.all()    
      

      【讨论】:

        【解决方案3】:
        1. 当然,所有与 request.user 相关的项目都很简单:

          Project.objects.filter(person=request.user)
          
        2. 从事这些项目的公司必然要求您循环浏览这些项目:

          for p in projects:
              p.company_set.all()
          
        3. UserCompanyCompany 上的任何其他外键之间没有任何关系,所以我不知道“员工”的概念来自哪里或如何获得那个。

        因为,这是非常基本的东西,我假设您的问题在于生成的 1*N 查询这一事实。在当前版本的 Django (1.3.1) 中,没有办法进一步优化这一点。在 Django 1.4 中,prefetch_related 允许您选择所有带有Projects 的公司(和员工)。但是,它仍然需要对每个关系进行唯一查询,因此总共需要 3 个来获取项目、公司和员工。它的工作原理是这样的:

        Project.objects.filter(person=request.user).prefetch_related('company')
        

        与此同时,我在使用django-batch-select 方面取得了一些成功,它基本上试图模仿prefetch_related 的行为。

        【讨论】:

        • 第 2 部分可以在没有 forloop 的情况下完成(因此它创建的额外数据库命中)...公司 = Company.objects.filter(project__in=projects)
        • 我的回答假设 OP 实际上希望保持项目与其公司之间的关联。是的,这将使所有公司都参与到任何项目中,但是您将失去按项目划分它们而不在事后以某种方式重新组合它们的能力。
        • 在 Python 中重新组合它们可以节省数据库调用(1 个查询对每个公司 1 个)。取决于对 OP 的特定场景来说什么是重要的。
        猜你喜欢
        • 2021-01-05
        • 2020-12-03
        • 2014-06-13
        • 2021-07-25
        • 1970-01-01
        • 2021-12-01
        • 1970-01-01
        • 2013-06-09
        相关资源
        最近更新 更多