Наконец-то! Уверен, что я не один воскликнул это слово, когда узнал что долгожданная queryset-refactor ветка влилась в транк и теперь ORM в джанго стал ещё лучше и удобней! Этого момента ждали долга, поскольку это один из самых больших шагов по направлению к 1.0 версии джанги. Итак, что же мы получили.
Начну с основных изменения уже имеющегося функционала:
Указание сортировки по при-join-ненным моделям теперь стало более логичным и совпадает с фильтрами lookup'ов. Просто пример:
Order.objects.all().order_by( "product__price" )Обновлена реализация
__iter__метода queryset'a. И не грузит все строки результат в память сразу.Особенно меня радует: сделана нормальная обработка None значения в lookup'ах. Т.е. если раньше приходилось писать писать воркэраунды для случая когда селект осуществлялся по
NULLзначениям, например так:if value is None: queryset = queryset.filter( field__isnull = True ) else: queryset = queryset.filter( field = value )То теперь эта проверка лишняя не нужна. Ура!)
Есть ещё некоторое количество изменений, но они на низко уровне и на прямую не влияют на использование. Хотя именно они окончательно убивают некоторые баги, которые были в джанговском ORM до сего момента.
Помимо изменений, есть ещё и целый ряд дополнений к возможностям ORM. Вот основные из них:
Добавлена возможность производить обновление(
UPDATE) нескольких объектов за раз. Это очень удобная возможность улучшить производительность достаточно частых ситуаций. Т.е. раньше для обновления объектов надо было "падать" до самого SQL и писать запросы вручную или делать совсем не оптимальные вещи типа таких:for entry in Entry.objects.filter( name = "Not so awesome..." ): entry.name = "Awesome!" entry.save()То теперь можно этот код сократить до одной элегантной строчки:
Entry.objects.filter( name = "Not so awesome..." ).update( name = "Awesome!" )-Появился метод
reverse, который разворачивает кверисет в обратном порядке сортировки. Иногда полезно.В
select_relatedможно добавить список relation полей которые должны быть зафетчены. Удобно, когда в модели много внешних связей и все тянут не нужно.Добавлен метод
values_list, который похож на старыйvaluesза исключение того что возвращает кортеж, а не словарь каждой строки результата. Давно напрашивающаяся функциональность, а то уже надоело из словарей доставать нужные значения.Одним из самых главных нововведений стало появление нормального наследования моделей. Причем в двух вариантах:
Абстрактные базовые классы. Покрывает на мой взгляд 95% случаев когда вообще нужно наследование моделей. Простой злободневный мой пример:
class BannerBase( models.Model ): url = models.URLField() hits = models.PositiveIntegerField( default = 0 ) class Meta: abstract = True ordering = ( "-hits", ) class TextBanner( BannerBase ): text = models.TextField() class Meta( BannerBase.Meta ): verbose_name = "текстовый баннер" class MediaBanner( BannerBase ): file = models.FileField( upload_to = "upload/banners/media" ) class Meta( BannerBase.Meta ): verbose_name = "медиа баннер"Основная суть в том, что для моделей, помеченных как
abstract = True, не создаются таблица, а они несут лишь некий общий функционал и описание для дочерних классов моделей. Так же имеется возможно наследовать мета-информацию. Важным замечание является то, чтоabstract = Trueне наследуется.Этот вариант более сложный, но тоже имеет случаи своего применения. Его суть заключается в том, что для каждой модели создается таблица, а дочерние связаны с родительской моделью посредством автоматически добавляемого
OneToOneFieldполя, которое также можно задать и вручную. Мета информацию как в первом варианте наследовать не имеет особого смысла, но такие поля какordering, если наследник не их перекроет, будут учитываться. Пример:class Visitor( models.Model ): last_action = models.CharField( max_length = 100 ) visit_count = models.PositiveIntegerField( default = 0 ) class RegistredVisitor( Visitor ): user = models.ForeignKey( User, related_name = "visitors" ) class GuestUser( Visitor ): raw_visitor = models.ForeignKey( Visitor, parent_link=True ) #явно задали связь name = models.CharField( max_length = 150 ) email = models.EmailField()Так же возможно и множественное наследование.
В общем очень мощный, полезный и удобный инструмент появился в наших руках.
Как вы видите новых возможностей в ORM появилось достаточно, чтобы уже считать его вполне конкурентоспособным по сравнению с самостоятельными монстрами этой сферы. Хотя конечно есть куда идти, например продолжаем все дружно ждать ждать GROUP BY, лучшую поддержку агрегатных функций и композитные первичные ключи.
Что на очереди? newforms-admin? Хотелось быть...
Комментарии 2
Бывает;)
Оставлен 27 Апрель 2008 в 12:36 ¶Спасибо Иван за замечание. Этот тонкий момент я упустил.
Оставлен 28 Апрель 2008 в 01:57 ¶Пингбеки 1
[...]Александр Кошелев[...]
Оставьте комментарий