Сегодня Малколм Трединник влил бранч queryset-refactoring в Джановский транк. Это изменение по крутости в принципе сравнимо с давнишней демагизацией. Однако в отличие от нее, на этот раз все гораздо более обратно совместимо.

Вообще, Малколм — велик. Фактически он переделал с нуля всю душу конструирования запросов в джанговском ORM, превратив ее из мельницы строковых кусочков в набор классов с четким разделением функциональности и возможностью гибкого наследования для ее расширения. И при этом умудрился сделать все так, чтобы обычный юзерский код не сломался. Мелкие исключения из обратной совметимости есть, но они действительно ерундовые.

На основе это кода уже сделано несколько вкусных улучшений. Первый пример — наследование моделей, про которое люди твердили прямо с первой публикации Джанго. Я, признаться, не нахожу его особо полезным, но отметить стоит.

Лично же мне почему-то особенно понравились две вещи:

Об остальных изменениях читайте в документе по бранчу на wiki.

Но главное, конечно, что теперь этот код гораздо проще контролировать и развивать. Например, агрегацию добавить...

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

  1. Nonexistent

    Прекрасная новость!

  2. Alex Lebedev

    Замечательно!

    Небольшая поправка:

    Department.objects.filter(employee__gender='male', employee__age__gte=40) — выбирает отделы, где есть мужчины старше 40 лет.

    Не старше 40, а 40 лет или старше. Суффикс gte — это "greater than or equal"

  3. Хрюндель

    А group_by это типа так.. мелочи..

  4. Иван Сагалаев

    Не старше 40, а 40 лет или старше.

    Буквоед :-). Поправил на "__gt".

  5. se

    Например, агрегацию добавить...

    Можно чуток поподробнее как это сделать. Подскажите в каком направлении копать.

  6. Иван Сагалаев

    Я имел в виду, что теперь разработчикам Джанго это будет просто реализовать. Поэтому прямо сейчас, чтобы это сделать, надо начать читать django-developers, понять положение вещей и, возможно, помочь кому-нибудь патч допилить.

  7. Александр Соловьёв

    Можно чуток поподробнее как это сделать. Подскажите в каком направлении копать.

    group by и аггрегация - это проект GSoC, и прямо сейчас их синтаксис обсуждается в django-developers.

  8. Макс Лапшин

    А у нас ещё красивей сделано:

    class Article < ActiveRecord::Base # это наследование
      has_finder :active, {:conditions => "active"}
      has_finder :search, lambda {|query| {:conditions =>
          ["name like :query or body like :query", {:query => "%"+query+"%"}]}}
      has_finder :of_user, lambda {|user_id| {:conditions => {:user_id => user_id}}}
      has_finder :limit, lambda {|limit| {:limit => limit}}
    end
    ...
    @articles = Article
    @articles = @articles.of_user(params[:user_id]) if params[:user_id]
    @articles = @articles.search(params[:query]) if params[:query]
    @articles = @articles.active if params[:active]
    @articles = @articles.limit(10)
    

    А у вас такие named_scope уже есть?

  9. Александр Соловьёв

    А у вас такие named_scope уже есть?

    Если бы вы ещё объясняли, что ж тут происходит... А то не всё прозрачно.

  10. Иван Сагалаев

    Саша! You made our day :-) Написать про код на Руби "а что это?" — это лучше, чем любая придуманная шутка :-).

    Макс, если по сути, то в статье речь не о наследовании от базового класса для всех моделей данных, оно в Джанго тоже есть. Сейчас появилось наследование юзерских моделей одна от другой. Например можно сделать модель Place, а от нее наследников Restaurant и Cinema. Джанго в этом месте решает вопросы, какие таблицы в базе создавать, как их связывать, и как в запросы включать.

    Но меня другая штука в коде удивила:

    {:query => "%"+query+"%"}]}}
    

    Если проценты надо добавлять вручную, то надо ли понимать, что и escape'ить проценты внутри query тоже надо вручную?

  11. Александр Соловьёв

    Саша! You made our day :-) Написать про код на Руби "а что это?" — это лучше, чем любая придуманная шутка :-).

    Не, ну все эти собачки, сбивающие с толку, и т.д. Тем более что я не понял, что ж такого особенного происходит в этом коде.

  12. Владимир Володин

    В наследовании нашел неприятный баг (особо неприятен он потому, что именно неработающую фичу я и хотел использовать).

    Как только прочитал о наследовании моделей, сразу подумал, ура! наконец-то можено унаследовать auth.models.User и делать с ним, что хочешь. Добавил в унаследованного пользователя ManyToManyField для реализации "дружбы" и выяснилось, что user1.friends.all() делает джойн на таблицу auth_user как раз по айдишнику юзера, друзей которого мы хотели найти. В итоге, если у user1 три друга, то user1.friends.all() выдаст нам [user1, user1, user1] вместо [user2, user3, user4].

  13. ruguevara

    Макс Лапшин, наверное, имеет в виду фильтрующие "менеджеры"?

Добавить комментарий