【问题标题】:Django: sorting by calculated criteria (advance case)Django:按计算标准排序(高级案例)
【发布时间】:2014-01-05 22:52:13
【问题描述】:

型号:

class Customer(models.Model):
    name = models.CharField(max_length=200)
    time_categoty = models.IntegerField()
    importance = models.IntegerField()

class Interaction(models.Model):
    i_date = models.DateTimeField()

class Interaction_customer(models.Model):
    interaction = models.ForeignKey(Interaction)
    customer = models.ForeignKey(Customer)

假设:

c = Customer.objects.get(pk=1)
x = Interaction.objects.filter(interaction_person__person=c).latest('i_date').i_date

(即给定客户的最新互动)

需要:所有客户的列表,按条件排序: time_category/(datetime.now() - x) * c.importance

请不要在 djangoproject.com 上给我一个“extra”的链接,我已经仔细阅读了它,但真的不知道如何在我的情况下实现它。 (案子很难,一个星期没人能帮忙,需要django-Jedi) 任何建设性的想法将不胜感激。 谢谢! //埃德

【问题讨论】:

  • 对不起,interaction_person__person == interaction_customer__customer
  • 1.最好将计算保存在某处,以便于排序(没有其他明确的方法可以做到这一点而不放弃一些效率) 2. 你的模型看起来像ManyToMany with a 'through'。我不知道这是否是您所说的“额外”,如果 Interaction_Customer 不添加自己的任何其他字段,我完全不明白您需要什么。最好直接链接它们
  • 我已经删除了所有与案例无关的字段,但真正的基础只需要这样的结构。 //埃德
  • 是否反对将 ManyToMany 与 'through' 结合使用?看起来像您正在寻找的设计
  • 是的,没错。这就是“通过”的目的。有关详细实施,请参阅我的答案。它只是让它们之间更容易直接连接

标签: django django-models django-queryset django-orm


【解决方案1】:

您在这里拥有的是与用于额外数据的第三个模型的多对多关系。通过链接它们,您可以获得直接连接它们的 api 的额外好处(这似乎是必要的)。现在至于手头的问题 - 让我们首先为客户创建一种计算数据的方法:

class Customer(models.Model):
    name = models.CharField(max_length=200)
    time_category = models.IntegerField()
    importance = models.IntegerField()
    interactions = models.ManyToManyField('Interaction', through='InteractionCustomer')

    def delta(self):
        ia = self.interactions.latest('i_date').i_date
        return self.time_categoty / ( datetime.now() - ia ) * self.importance

class Interaction(models.Model):
    i_date = models.DateTimeField()

class InteractionCustomer(models.Model):
    interaction = models.ForeignKey(Interaction)
    customer = models.ForeignKey(Customer)

现在我们要按它排序。你可以用python做到这一点:

 sorted( Customer.objects.all(), key=lambda x: x.delta() )

或者,为了提高效率,您可以将其保存到另一个字段。尽管在这种情况下,您需要不断更新它。您可以覆盖 save 方法,但这仅适用于保存手头的 Customer 对象,情况可能并非总是如此(因此在以这种方式实现时需要仔细考虑):

class Customer(models.Model):
    ....
    delta = models.IntegerField()

    def save(self, *args, **kwargs):
        self.delta = self.calc_delta()
        super(Customer, self).save(*args, **kwargs)

【讨论】:

  • 感谢您的专业精神和乐于助人的意愿!该方法易于实现,效果很好!
  • 没问题!很高兴能帮上忙=]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
  • 2014-05-06
相关资源
最近更新 更多