Как вы упорядочиваете списки таким же образом, как QuerySets упорядочены в Django? - PullRequest
1 голос
/ 16 апреля 2009

У меня есть модель, у которой есть поле для заказа в своем мета-классе. Когда я выполняю запрос и возвращаю QuerySet для модели, он находится в указанном порядке. Однако, если у меня есть экземпляры этой модели, которые находятся в списке, и я выполняю метод сортировки в списке, порядок отличается от того, который я хочу. Есть ли способ сортировки списка экземпляров модели так, чтобы порядок был равен указанному в определении модели?

Ответы [ 3 ]

3 голосов
/ 16 апреля 2009

Не автоматически, но с небольшим количеством работы, да. Вам необходимо определить функцию сравнения (или метод cmp в классе модели), который может сравнивать два экземпляра модели в соответствии с соответствующим атрибутом. Например:

class Dated(models.Model):
  ...
  created = models.DateTimeField(default=datetime.now)

  class Meta:
    ordering = ('created',)

  def __cmp__(self, other):
    try:
      return cmp(self.created, other.created)
    except AttributeError:
      return cmp(self.created, other)
3 голосов
/ 16 апреля 2009

Ответ на ваш вопрос в различной степени - да, с некоторыми ручными требованиями. Если под list вы подразумеваете queryset, который был сформирован каким-то сложным запросом, тогда, конечно:

queryset.order_by(ClassName.Meta.ordering)

или

queryset.order_by(instance._meta.ordering)

или

queryset.order_by("fieldname") #If you like being manual

Если вы не работаете с набором запросов, то, конечно, вы все равно можете сортировать, точно так же, как любой сортирует сложные объекты в python:

  • Компараторы
  • Указание ключей
  • Украсьте / Сортировка / Undecorate

См. Вики Python для подробного объяснения всех трех.

2 голосов
/ 17 апреля 2009

Опираясь на ответ Карла, вы можете легко добавить возможность использовать все поля порядка и даже определять те, которые находятся в обратном порядке.

class Person(models.Model):
  first_name = models.CharField(max_length=50)
  last_name = models.CharField(max_length=50)
  birthday = date = models.DateField()

  class Meta:
    ordering = ['last_name', 'first_name']

  def __cmp__(self, other):
    for order in self._meta.ordering:
      if order.startswith('-'):
        order = order[1:]
        mode = -1
      else:
        mode = 1
      if hasattr(self, order) and hasattr(other, order):
        result = mode * cmp(getattr(self, order), getattr(other, order))
        if result: return result
    return 0
...