Сегодня Малколм Трединник влил бранч queryset-refactoring в Джановский транк. Это изменение по крутости в принципе сравнимо с давнишней демагизацией. Однако в отличие от нее, на этот раз все гораздо более обратно совместимо.
Вообще, Малколм — велик. Фактически он переделал с нуля всю душу конструирования запросов в джанговском ORM, превратив ее из мельницы строковых кусочков в набор классов с четким разделением функциональности и возможностью гибкого наследования для ее расширения. И при этом умудрился сделать все так, чтобы обычный юзерский код не сломался. Мелкие исключения из обратной совметимости есть, но они действительно ерундовые.
На основе это кода уже сделано несколько вкусных улучшений. Первый пример — наследование моделей, про которое люди твердили прямо с первой публикации Джанго. Я, признаться, не нахожу его особо полезным, но отметить стоит.
Лично же мне почему-то особенно понравились две вещи:
Если у вас есть модель Department и у ней есть зависимая модель Employee, то можно сделать две разные вещи:
Department.objects.filter(employee__gender='male', employee__age__gt=40)
— выбирает отделы, где есть мужчины старше 40 лет. То есть оба условия пола и возраста накладывается на каждого сотрудника.Department.objects.filter(employee__gender='male').filter(employee__age__gt=40)
— выбирает отделы, где есть мужчины — раз, и из них те отделы, где есть люди старше 40 лет — два. Тут условия накладываются отдельно одно за другим на всех сотрудников отдела.
Другими словами, Джанго научилась делать join с несколькими копиями одной и той же таблицы в одном запросе.
Можно делать массовый update:
Employee.objects.filter(salary=20000).update(salary=50000)
Об остальных изменениях читайте в документе по бранчу на wiki.
Но главное, конечно, что теперь этот код гораздо проще контролировать и развивать. Например, агрегацию добавить...
Комментарии: 13
Прекрасная новость!
Замечательно!
Небольшая поправка:
Не старше 40, а 40 лет или старше. Суффикс
gte
— это "greater than or equal"А group_by это типа так.. мелочи..
Буквоед :-). Поправил на "__gt".
Можно чуток поподробнее как это сделать. Подскажите в каком направлении копать.
Я имел в виду, что теперь разработчикам Джанго это будет просто реализовать. Поэтому прямо сейчас, чтобы это сделать, надо начать читать django-developers, понять положение вещей и, возможно, помочь кому-нибудь патч допилить.
group by и аггрегация - это проект GSoC, и прямо сейчас их синтаксис обсуждается в django-developers.
А у нас ещё красивей сделано:
А у вас такие named_scope уже есть?
Если бы вы ещё объясняли, что ж тут происходит... А то не всё прозрачно.
Саша! You made our day :-) Написать про код на Руби "а что это?" — это лучше, чем любая придуманная шутка :-).
Макс, если по сути, то в статье речь не о наследовании от базового класса для всех моделей данных, оно в Джанго тоже есть. Сейчас появилось наследование юзерских моделей одна от другой. Например можно сделать модель Place, а от нее наследников Restaurant и Cinema. Джанго в этом месте решает вопросы, какие таблицы в базе создавать, как их связывать, и как в запросы включать.
Но меня другая штука в коде удивила:
Если проценты надо добавлять вручную, то надо ли понимать, что и escape'ить проценты внутри query тоже надо вручную?
Не, ну все эти собачки, сбивающие с толку, и т.д. Тем более что я не понял, что ж такого особенного происходит в этом коде.
В наследовании нашел неприятный баг (особо неприятен он потому, что именно неработающую фичу я и хотел использовать).
Как только прочитал о наследовании моделей, сразу подумал, ура! наконец-то можено унаследовать auth.models.User и делать с ним, что хочешь. Добавил в унаследованного пользователя ManyToManyField для реализации "дружбы" и выяснилось, что user1.friends.all() делает джойн на таблицу auth_user как раз по айдишнику юзера, друзей которого мы хотели найти. В итоге, если у user1 три друга, то user1.friends.all() выдаст нам [user1, user1, user1] вместо [user2, user3, user4].
Макс Лапшин, наверное, имеет в виду фильтрующие "менеджеры"?