加速Django向后关系查询

时间:2014-11-26 11:10:28

标签: django django-models django-views django-queryset

对于我的应用,我定义了以下模型:

class Person(CrunchrModel):
    MALE = "M"
    FEMALE = "F"
    OTHER = "O"
    UNKNOWN = "U"
    GENDER_CHOICES = (
            (MALE, "Male"),
            (FEMALE, "Female"),
            (UNKNOWN, "Other"),
    )

    firstName       = models.CharField(max_length=200, null=True, db_column="firstname")
    lastName        = models.CharField(max_length=200, null=True, db_column="lastname")
    gender          = models.CharField(max_length=1, choices=GENDER_CHOICES, default=UNKNOWN, null=True)
    dateOfBirth     = models.DateField(null=True, db_column="dateofbirth")
    dateInService   = models.DateField(null=True, db_column="dateinservice")
    photo           = models.ImageField(upload_to='person_photos', null=True)


class Position(Protected):
    positionId      = models.CharField(max_length=200, unique=True, db_column="positionid")
    title           = models.CharField(max_length=200, null=True)
    # There cannot be a DB constraint, as that would make it impossible to add the first position.
    dottedLine      = models.ForeignKey("Position", to_field='positionId', related_name="Dotted Line",
                                        null=True, db_constraint=False, db_column="dottedline_id")
    solidLine       = models.ForeignKey("Position", to_field='positionId', related_name="SolidLine", 
                                        null=True, db_constraint=False, db_column="solidline_id")
    grade           = models.ForeignKey(Grade)
    businessUnit    = models.ForeignKey(BusinessUnit, null=True, db_column="businessunit_id")
    functionalArea  = models.ForeignKey(FunctionalArea, db_column="functionalarea_id")
    location        = models.ForeignKey(Location, db_column="location_id")


class Employee(models.Model):
    person                = models.OneToOneField(Person, db_column="person_id")
    fte                   = models.IntegerField(default=100)
    dataSource            = models.ForeignKey(DataSource, db_column="datasource_id")
    talentStatus          = models.ForeignKey(TalentStatus, db_column="talentstatus_id")
    retentionRisk         = models.ForeignKey(RetentionRisk, db_column="retentionrisk_id")
    retentionRiskReason   = models.ForeignKey(RetentionRiskReason, db_column="retentionriskreason_id")
    performanceStatus     = models.ForeignKey(PerformanceStatus, db_column="performancestatus_id")
    potential             = models.ForeignKey(Potential, db_column="potential_id")
    mobility              = models.ForeignKey(Mobility, db_column="mobility_id")
    currency              = models.ForeignKey(Currency, null=True, db_column="currency_id")
    grade                 = models.ForeignKey(Grade, db_column="grade_id")
    position              = models.OneToOneField(Position, to_field='positionId', null=True, 
                                                 blank=True, db_column="position_id")
    employeeId            = models.CharField(max_length=200, unique=True, db_column="employeeid")
    dateInPosition        = models.DateField(null=True, db_column="dateinposition")


class Succession(models.Model):
    position    = models.ForeignKey(Position, to_field='positionId', db_column="position_id")
    employee    = models.ForeignKey(Employee, to_field='employeeId', db_column="employee_id")
    term        = models.ForeignKey(SuccessionTerm)

我正在尝试建立一个继任网络。为此,我正在创建一个表格,其中包含每位员工的职位ID,姓名,职位以及他/她排队等候的职位。

我有一个工作视图,但由于一些效率低下的查询,它很慢:

 employees = Employee.objects.all().prefetch_related('person', 'position')
 successions = Succession.objects.all().prefetch_related('position', 'employee')

 for emp in employees:
     succeeds = []
     for s in successions.filter(employee=emp):
         succeeds.append(s.position.positionId)
 # Store emp.position.positionId, emp.person.lastName, emp.position.title, succeeds

有没有办法,不使用原始SQL(由于应用程序中的其他限制),使这更有效?

1 个答案:

答案 0 :(得分:1)

我认为您不需要原始SQL:您应该能够在Employee prefetch_related中遵循与Succession的关系。您根本不需要单独查询Succession。

employees = Employee.objects.all().prefetch_related('person', 'position', 'succession_set__position')

现在,在您的模板中,您可以迭代它:

{% for emp in employees %}
  {{ emp.position.title }
  {% for succ in emp.succession_set.all %}
      {{ succ.position.title }}
  {% endfor %}
{% endfor %}