Страницы

Поиск по вопросам

воскресенье, 9 февраля 2020 г.

Сортировка с условием

#python #queryset #django


Как мне сделать такую штуку. Есть класс активности, есть класс занятия (урок). У
каждой активности есть тип и дата. Количество типов конечно и мало. Мне надо отсортировать
объекты типа занятие по дате активности определенного типа. Не могу понять как сделать.
Можно ли замутить что-то подобное:
Leson.objects.filter(action__type="w").order_by(action__type="w", "-action__date").distinct()

Но естественно так работать не будет. А как написать так, чтоб работало?
Обновление: Идея в том, что сначала я фильтрую по типу активности, а затем хочу отсортировать
по дате активности. Проблема в том, что надо отсортировать по активности определенного
типа. К примеру, я отфильтровал объекты. У меня получилось следующее
Объект А имеет поля
активность { тип: "w", дата 11-01-01 }
активность { тип: "g", дата 11-04-07 }
активность { тип: "r", дата 11-03-06 }
....

Объект B имеет поля
активность { тип: "w", дата 11-10-01 }
активность { тип: "r", дата 11-03-03 }
....

То есть остались только те объекты, у которых есть активности типа "w". А вопрос
в следующем, как теперь их отсортировать по дате активности типа "w"? Если просто написать
order_by("-action__date"), то сортировать будет по всем активностям данного объекта,
а мне надо учесть только определенный тип.

Если выбрать объекты в массив, а потом в ручную сортировать, идея не самая лучшая,
объектов очень много, а к каждого объекта много активностей.
Обновление 2: 
class Lesson(BaseModel):
    __metaclass__ = LessonMetaClass
    ...
    # Еще много полей

class Action(BaseModel):
    lesson = models.ForeignKey('Lesson', null=True, related_name="actions")
    type = models.CharField(max_length=32)
    date = models.DateTimeField(default=datetime.datetime.now)

На выходе я хочю получить отсортированный QuerySet.    


Ответы

Ответ 1



Что значит "по дате активности определённого типа"? Если у вас какая-то iterable коллекция, то можно отсортировать функцией sorted (для списков есть метод сорт). Рисуете функцию, задающую порядок и вперёд. Например: def mycmp(o1, o2): if(o1.activity == o2.activity): return cmp(o1.date, o2.date) else: return cmp(o1.activity, o2.activity) a=sorted(lessons, mycmp) Это немного не то, что надо по условию задачи, но оно (это условие) непонятно. Желательно бы исходное условие пояснее.

Ответ 2



Честно сказать вообще не понятно, что вы хотите сделать отфильтровать или отсортировать надо отсортировать объекты типа занятие по дате активности определенного типа. если вам нужны уроки только данного типа отсортированные по дате активности, то по идее надо делать так Leson.objects.filter(action__type="w").order_by("-action__date").distinct() если нужны все уроки, отсортированные по типу и дате активности, то Leson.objects.all().order_by("action__type", "-action__date").distinct() если же надо что-то другое, то поясните что именно. Насколько я понял из обновления у одного урока несколько активностей, собственно в чем и загвоздка получается, только я не понял в каком они отношении. Думаю код моделей бы все прояснил. Вполне возможно, что вам придется фильтровать и сортировать активности, а потом получать уроки этих активностей (опять же, если я все правильно понял). Т.е. что-то вроде Lesson.objects.filter(activity__in=Activity.objects.filter(type="w").order_by('-date')) Обновление В данный момент мне в голову приходит только такой вариант: lessons = [] for active in Active.objects.filter(type='w').order_by('-date'): lessons.append(active.lesson) Обновление 2 Тогда вам надо смотреть на raw sql queries: lessons = Lesson.objects.raw("""SELECT DISTINCT FROM youapp_lesson AS l INNER JOIN youapp_active AS a ON a.lesson_id = l.id WHERE a.type='w' ORDER BY a.date DESC""") P.S. Кстати, еще очень хорошо посмотреть что формирует обычный ORM запрос. Очень помогает определить в каком направлении и как надо двигаться.

Ответ 3



возможно вам поможет мой опыт в чем то подобном: у меня стояла зада добавить множество фильтров сортировки которые могут быть иногда "пустыми", при помощи регекспов у меня получилось воспроизвести все что мне нужно дополнительно я использовал django-sorting, django-pagination (их можно найти на гит хабе) часть кода из views: if request.GET.get('phone'): phone = request.GET.get('phone') else : phone = r'^[0-9]' if request.GET.get('poz'): poz = request.GET.get('poz') else : poz = r'^[0-9]' acc = accounts.objects.filter(name__regex=poz).filter(account__regex=phone).exclude(status=9) django-sorting легко настраиваемый ЗЫ если вы получили QuerySet и потом хотите что то с ним делать , то это тоже не проблема : >>> acc = accounts.objects.all() >>> acc [, , , '...(remaining elements truncated)...'] >>> acc.exclude(status=9) [, , , , '...(remaining elements truncated)...'] >>> acc.filter(id=4) [] то есть вы можете отсортировать тех у которых есть активности типа "w", а потом уже отдельно отфильтровать как вам удобно : как то так type_w = Leson.objects.filter(action__type="w") type_w.order_by("-action__date")

Комментариев нет:

Отправить комментарий