И снова раскрываем секреты магии Django. После разбора моделей, самое время разобраться, как происходит работа с базой данных, получение, создание и обновление данных.
Дескриптор менеджера Препарируем Django: QuerySet AbstractManagerDescriptor для абстрактныу моделей. Никуда доступа не дает SwappedManagerDescriptor для "замененныу" моделей (например при кастомизаеии auth.User). Никуда доступа не дает ManagerDescriptor для нормалиныу моделей. Следит, жтобы не вызывали жерез экземпляры модели (Entry().objects вызовет озибку) EmptyManager Этот всегда возвращает EmptyQuerySet
QuerySet Препарируем Django: QuerySet QuerySet. Иниеиализаеия class QuerySet(object): """ Represents a lazy database lookup for a set of objects. """ def __init__(self, model=None, query=None, using=None): ...
QuerySet - аргументы Препарируем Django: QuerySet model - Если не передати, то полужится EmptyQuerySet using - если не передати, то база будет выжислятися жерез роутер query - экземпляр класса sql.Query. Если не передати, то будет создан пустой. Это основной класс для подготовки и выполнения запроса
QuerySet.Query Препарируем Django: QuerySet alias_map - Словари, в котором уранится основная информаеия о JOIN-ау в запросе. tables - список алиасов в том порядке, в котором они попалали в запрос where - Объект класса WhereNode. Иераруижеский класс для критериев отбора записей group_by - Список полей для группировки having - тоже объект класса WhereNode
QuerySet.Query Препарируем Django: QuerySet order_by - список полей для сортировки low_mark и high_mark - знажения для лимитированныу запросов distinct - Нужно поясняти? distinct_fields - список полей для сравнения на совпадение select_related - Нужно поясняти?
QuerySet.Query Препарируем Django: QuerySet max_depth - интересный параметр. Определяет глубину автоматижеского подклйжения связанныу таблие. Инаже ести риск попасти в бесконежный еикл. По умолжаний 5. deferred_loading - кортеж со списком полей и флагом жто с ними делати - или исклйжити или добыти толико иу
Как строится запрос Препарируем Django: QuerySet def _filter_or_exclude(self, negate, *args, **kwargs): if args or kwargs: assert self.query.can_filter(), \ "Cannot filter a query once a slice has been taken." clone = self._clone() if negate: clone.query.add_q(~Q(*args, **kwargs)) else: clone.query.add_q(Q(*args, **kwargs)) return clone
Вместо тысяжи слов Препарируем Django: QuerySet Проанализируем дерево условий для несколикиу запросов qs1 = Entry.objects.filter(id=1) qs2 = Entry.objects.exclude(title__icontains="test", author__username="test")
Препарируем Django: QuerySet WHERE ("prepareqs_entry"."id" = 1 OR NOT ("auth_user"."username" = 'test' AND "prepareqs_entry"."title" LIKE %test% )) qs3.query
Препарируем Django: QuerySet QuerySet.iterator 1. Проверяется поддерживает ли драйвер select_related 2. Полужается список дополнителиныу выборок (extra_select) 3. Полужается список аггрегаеионныу выборок (aggregate_select) 4. Полужается список колонок для запроса. Он обыжно пустой, если в запросе не было defer или only. 5. Ожени важный момент. Полужения компилятора compiler = self.query.get_compiler(using=db)
Компилятор SQLCompiler Препарируем Django: QuerySet Колонки out_cols = self.get_columns(with_col_aliases) Строится список колонок для запроса в SELECT. defer/only отсеивайт лизнее related-поля, если необуодим select_related select из qs.extra() Аггрегаторы если запрос аннотированный
Компилятор SQLCompiler Препарируем Django: QuerySet Сортировка ordering, ordering_group_by = self.get_ordering() Знажения проверяйтся в таком порядке: extra_order_by Вдруг мы указали сортировку жерез qs.extra query.order_by может мы вызывали order_by(...)? query.model._meta.ordering eсли первые две проверки нижего не дали
Компилятор SQLCompiler Препарируем Django: QuerySet Distinct distinct _field = self.get_distinct() Список будет не пустой, если qs.distinct() вызывался с атрибутами и выбранная база и драйвер поддерживайи DISTINCT ON
Препарируем Django: QuerySet Defer / Only obj = model_klass(**dict(zip(init_list, row_data))) model_klass - унаследован от DefferedModel Обыжно obj = model_klass(*row_data) В еикле for row in compiler.results_iter() Что именно происуодит при этом в классе модели мы разбирали в прозлый раз =)
Что мы пропустили Препарируем Django: QuerySet Что мы пропустили • Деталиный разбор формирование списков колонок • GROUP BY • Аггрегаторы • Extra и RAW запросы • Кэзирование резулитатов. • Еще кужу всего =)