【问题标题】:Django QuerySet order_by string evaluationDjango QuerySet order_by 字符串评估
【发布时间】:2011-04-30 03:53:01
【问题描述】:

我正在尝试根据 QuerySet 中的对象作为字符串的评估方式对我的 QuerySet 进行排序。

所以我的模型看起来像这样:

class System(models.Model):
  operating_system = models.CharField(...)
  language = models.CharField(...)
  locale = models.CharField(...)

  def __unicode__(self):
    def __clean(orig, new):
      if orig is None or orig == "":
        if new is None or new == "":
          return ""
        else:
          return str(new)
      else:
        if new is None or new == "":
          return str(orig)
        else:
          return str(orig) + " " + str(new)
    name = None
    for attr in System._meta.fields:
      if attr.name != "id":
        name = __clean(name, getattr(self, attr.name))
    for m2mfield in System._meta.many_to_many:
      for object in getattr(self, m2mfield.name).all():
        name = __clean(name, object)  

    if name == "":
      return "Undefined"
    return name

而且,我希望能够进行如下查询:

System.objects.filter(...).order_by('__unicode__')

我想知道是否有办法在没有自定义管理器的情况下做到这一点。

谢谢!

【问题讨论】:

  • 即使使用自定义管理器也做不到。
  • 您会考虑保存作为字符串值的非规范化字段,而不是那种hackery?我的意思是在你的系统模型上抛出另一个字段,并在必要时通过覆盖 save() 来更新它,然后你可以按这个其他字段排序...
  • @Henry 您能否详细说明非规范化字段与我当前使用的字段的区别是(或给我一个指针?)谢谢。那肯定行得通。虽然,感觉有点浪费空间?

标签: python django django-models django-queryset


【解决方案1】:

__unicode__ 中,您最终会得到一个表示系统对象的字符串。与其每次需要时都计算,不如计算一次并保存到模型中。

class System(models.Model):
    operating_system = models.CharField(...)
    language = models.CharField(...)
    locale= models.CharField(...)
    name = models.CharField(editable=False, ...)

    def save(self, *args, **kwargs):
        self.name = self._calculate_name()
        super(System, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.name

    def _calculate_name(self):
        # all that string manipulation and relationship stuff

现在您可以轻松按此名称订购

System.objects.filter(...).order_by('name')

这种方法有一些注意事项,它实际上取决于 System.另外,不要担心空间,这是我的意见!


扩展注意事项

由于该字段是“非规范化”的,因此它会遇到与其他未规范化的关系数据相同的问题。 Denormalization 可以引入更新异常(name 所依赖的字段或关系可以在不更改 name 的情况下更改,如果更改是通过 System 模型的 save() 方法之外的其他途径发生的。它也可以减慢向下写入(在这种情况下可能会增加很小的数量),它可以增加空间需求(在我看来这也不是问题),以及谷歌很想告诉你的一大堆其他东西我敢肯定。

我认为您需要注意的只是随时更新.name,因此请仔细考虑在什么情况下您的“清理”代码会产生不同的结果。例如,如果您有一个 OS 表,您可以在其中更改 OS 的描述而无需触及 System 表,那么您必须意识到您的 .name 不会通过保存到 OS 来更新,它将需要重新计算。有一些机制可以帮助解决这个问题,比如信号和覆盖更多 save() 方法。您还可以根据需要批量更新它们。

这在很大程度上取决于您的用例,这里没有完全说明。如果您更完整地展示您的用例,SO 有很多人可以帮助您缩小最佳解决方案的范围。

【讨论】:

  • 谢谢亨利!这可能会做到。您能否简要介绍一下这种方法的注意事项?
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 2022-09-28
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 2012-11-17
  • 2014-10-26
  • 2017-03-29
相关资源
最近更新 更多