Сегодня наконец-то отбросил свою лень в сторону и сделал то, о чём так долго твердили большевики! :)
Перед всем этим текстом хочу сказать спасибо Диме Догадайло, который собственно всё это и сделал. Недавно он мне говорил, что хочет этот код выложить в опенсорс, но так как этого пока не произошло - я значит буду первый, благо он мне разрешил код использовать в блоге. :-)
В Джанге, как известно, встроен свой механизм аутентификации, который часто бывает довольно удобен (самое большое удобство заключается именно в его встроенности - интеграции со всем джанговским хозяйством), но имеет одну принципиальную проблему: модель пользователя самого практически нереально расширять.1 Пока из адекватных рабочих путей (т.е. даже если смотреть по сторонам, не обращая внимания на слова “гарантированный”, “официальный”, “документированный” ;) есть только создание отдельной модели - профиля (всем заинтересованным - читать пост Джеймса Беннетта, благо он хорошо описал2), но при этом сразу возникает другая проблема - профиль, живущий в отдельной модели, подтягивается к объекту юзеру в общем случае отдельным запросом.
В принципе, эту проблему должен решать select_related
, но он же идёт только по
прямым ссылкам, а не обратным - т.е. для профилей бы он вытягивал пользователей,
но не наоборот. Проблема эта решаема, решать её можно по-разному - и я её
решил несколько иначе, приспособив и без того полезную штуку.
Штука эта - несколько функций, которые позволяют загружать обратные связи за один запрос. Т.е. если мы получаем 5 постов в блог, а потом к ним комментарии - это выходит 2 запроса в базу, а не 6 (1 на посты и 5 на комментарии к каждому). В принципе, никакого rocket science’а нету, но я за время работы с джангой всегда изворачивался другим образом, если попадал на подобные грабли - не всегда это было лучше, но кое-как выходило. :-) И вот эти функции я использовал для подгрузки профилей к пользователям в отображении комментариев здесь, что уменьшило количество запросов на каждый пост в разы. :)
Я ещё успел натолкнуться на проблему, что рассчитано это было на что-то подобное “последним двадцати постам или картинкам” - уникальным объектам, и из-за этого кэш получал только первый объект из тех, кто его хотел. А в случае с комментариями такое не прокатывает никак, тут один и тот же человек комментирует несколько раз. :-) Это меня и заставило разобраться в коде и добавить поддержку неуникальных объектов.
Думаю, что прямо здесь код приводить особого смысла нету, но вот сами функции, а тут их использование.
P.S. После написания этого поста и игр с sup
мне захотелось сделать сноски,
подобные тем, что есть у Адама Гомаа. :-)
-
мне кажется, что с помощью переделки модели юзера в создающуюся динамически эту проблему можно решить. ↩︎
-
хотя я использую
AutoOneToOneField
Ивана Сагалаева, но большой роли это не играет. :) ↩︎