简体   繁体   English

Django QuerySet order_by 字符串评估

[英]Django QuerySet order_by string evaluation

I'm trying to sort my QuerySet based on how the objects in the QuerySet are evaluated as Strings.我正在尝试根据 QuerySet 中的对象如何评估为字符串来对我的 QuerySet 进行排序。

So my model looks something like this:所以我的 model 看起来像这样:

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

And, I'd like to be able to make a query something like:而且,我希望能够进行如下查询:

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

I'm wondering if there's a way to do this without a custom manager.我想知道是否有办法在没有自定义管理器的情况下做到这一点。

Thanks!谢谢!

In __unicode__ you eventually end up with a single string that represents a System object.__unicode__中,您最终会得到一个代表系统 object 的字符串。 Instead of calculating it every time you need it, calculate it once and save it onto the model.无需每次需要时都计算,而是计算一次并将其保存到 model 中。

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

Now you can order by this name easily现在您可以轻松按此名称订购

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

There are some caveats to this approach, it really depends on the usage of System.这种方法有一些注意事项,它实际上取决于 System. Also, do NOT worry about the space, that's my opinion!另外,不要担心空间,这是我的意见!


Expanding on caveats扩展注意事项

Since this field is 'denormalized', it suffers from the same problems other relational data that isn't normalized face.由于该字段是“非规范化”的,因此它会遇到与其他未规范化的关系数据相同的问题。 Denormalization can introduce update anomalies (a field or relation that name depends on can change without a change to name if the change happens through some other route than the System model's save() method. It can also slow down writes (in this case probably by a very small amount), it can increase space requirements (again not a problem here in my opinion), and a whole wack of other stuff that Google would love to tell you about I'm sure.非规范化可以引入更新异常(如果更改通过System模型的save()方法以外的其他途径发生,则name所依赖的字段或关系可以更改而不更改name 。它还可以减慢写入速度(在这种情况下可能通过很小的数量),它可以增加空间需求(在我看来这也不是问题),以及谷歌很想告诉你的一大堆其他东西我敢肯定。

I think all you have to be careful about is updating .name whenever it should be, so consider carefully under what conditions your 'cleaning' code will produce different results.我认为您需要注意的只是随时更新.name ,因此请仔细考虑在什么条件下您的“清理”代码会产生不同的结果。 If, for example, you had an OS table where you can change the description of an OS without touching the System table, then you have to realize your .name will not be updated by a save to OS, it will require recalculation.例如,如果您有一个 OS 表,您可以在其中更改 OS 的描述而无需触及 System 表,那么您必须意识到您的.name不会通过保存到 OS 来更新,它将需要重新计算。 There are mechanisms to help with this like signals and overriding more save() methods.有一些机制可以帮助解决这个问题,比如信号和覆盖更多的save()方法。 You could also batch update them as necessary.您还可以根据需要批量更新它们。

It really depends heavily on your use case, which is not fully illustrated here.这在很大程度上取决于您的用例,这里没有完全说明。 SO is full of people that could help you narrow down the best solution if you present your use case more completely.如果您更完整地展示您的用例,SO 有很多人可以帮助您缩小最佳解决方案的范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM