Якось зайшла мова в одній комюніті про легкий фреймворк на Python для невеличких сайтів.
Ось невеличка презентація. Буде трошки вільного часу, треба буде покурити мануал і потестувати.
Перша оптимізація Django
Закінчив загальну свою першу оптимізацію проекту на Django. Цікаво і круто. Підгадаю, на стартовій сторінці в мене виконувалось більше 300 запитів, від чого я мало не впав і не розчарувався в "Object-relational mapping". Оптимізація з кешуванням зараз дає результат в 30 дуже легеньких запитів і в час неактуальності кешу ще біля десятка, але також легеньких.
Основне зло, з яким довелось боротись:
Висновок: Django дуже рулить. Все надзвичайно слухняне + хороша реалізація фреймворку кешування = хороший результат.
Основне зло, з яким довелось боротись:
- django-tagging. Дуже корисна і зручна бібліотека міток, але має в post-init два запити і любе звертання до моделі, в якій використовується поле міток множить кількість запитів на 3. Там де мітки не використовуються, лікується через .defer('tags');
- В мене кілька пов'язаних моделей і використовується в URL два slug з різних моделей. Звісно по документації описав генерацію URL у get_absolute_url і в результаті отримав у вибірках кількість запитів * 2. Так як в мене кешуються ці моделі, то у шаблонах через template tags по ID я вибирав потрібні значення з інших моделей з кешу, в результаті позбувся цього зла;
Висновок: Django дуже рулить. Все надзвичайно слухняне + хороша реалізація фреймворку кешування = хороший результат.
оптимізація і django-tagging
Взявся за оптимізацію проджекту, запустив монітор запитів і офігів, на стартовій більше 300 запитів.
А виною всього виявився django-tagging, який запускає post-init і на кожен об'єкт отримуємо + 2 додаткових запити.
Вирішується досить просто. У запит додаємо defer('tags')
django-tagging і get_by_model з логікою OR
Хороша ліба django-tagging, яка дозволяє тегувати все що завгодно. Вибірку по тегах можна зробити методом get_by_model.
TaggedItem.objects.get_by_model(Post, [u'духовність',u'культура',u'мистецтво'])і ми отримаємо об'єкти з наступними тегами але з логікою "і". Але мені потрібно такий самий метод, але з логікою "або", тобто вибрати об'єкти де зустрічається хоча би один з перелічених тегів. Мій варіант методу. Трошки говнокод, але працює. Колись може дойдуть руки навести есетичний марафєт.
def get_by_model_or(self, queryset_or_model, tags):
tags = get_tag_list(tags)
tag_count = len(tags)
if tag_count == 0:
queryset, model = get_queryset_and_model(queryset_or_model)
return model._default_manager.none()
queryset, model = get_queryset_and_model(queryset_or_model)
content_type = ContentType.objects.get_for_model(model)
opts = self.model._meta # return tagging.taggeditem
tagged_item_table = qn(opts.db_table) # `tagging_taggeditem`
where = []
where.append('%s.content_type_id = %%s' % tagged_item_table,)
or_string = "("
or_tuple = ()
params = [content_type.pk]
for i in range(len(tags)):
if i == 0:
or_string += "%s.tag_id = %%s "
else:
or_string += "OR %s.tag_id = %%s "
or_tuple += (tagged_item_table,)
params.append(tags[i].pk)
or_string += ")"
where.append(or_string % or_tuple)
where.append('%s.%s = %s.object_id' % (qn(model._meta.db_table),
qn(model._meta.pk.column),
tagged_item_table))
return queryset.extra(
tables=[opts.db_table],
where=where,
params = params
)
Django + TinyMCE + Django-tinymce-filebrowser
Як бісить, коли оупенсорсним програмістам впадло писати хоча би мінімальну документацію. Інколи доводиться курити годинами мануали.
Цей раз не виключення. Потрібно прикрутити до HTML-едітора файловий браузер (заванаження малюночків на сервер і вставка їх в документ). Одне з легеньких рішень Django-tinymce-filebrowser. Але ні слова не вказано про ініціалізацію цього аппа.
Тож:
{% block head_extra %}
<script src="{{ settings.TINYMCE_JS_URL }}" type="text/javascript"></script>
<script type="text/javascript">
tinyMCE.init({
mode: "textareas",
theme: "advanced",
language : 'uk',
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : "True",
file_browser_callback : "mce_filebrowser"
});
function mce_filebrowser(field_name, url, type, win) {
var cmsURL = "/tinymce-fb/image";
if (cmsURL.indexOf("?") < 0) {
cmsURL = cmsURL + "?type=" + type;
}
else {
cmsURL = cmsURL + "&type=" + type;
}
tinyMCE.activeEditor.windowManager.open({
file : cmsURL,
title : 'My File Browser',
width : 420,
height : 400,
resizable : "yes",
inline : "yes",
close_previous : "no"
}, {
window : win,
input : field_name
});
}
</script>
{% endblock %}
шаблонний фільтр для числівників
Інколи потрібно разом з цифрою вказати слово у вірній множині. Наприклад: 1 коментар, 9 коментарів, 2 коментарі. Django в комплекті має багато шаблонних фільтрів, але для нашої солов'їної треба написати власний.
# -*- coding: utf-8 -*-
from django import template
register = template.Library()
@register.filter
def uapluralize(value, arg="дурак,дураки,дураків"):
args = arg.split(",")
number = abs(int(value))
a = number % 10
b = number % 100
if (a == 1) and (b != 11):
return args[0]
elif (a >= 2) and (a <= 4) and ((b < 10) or (b >= 20)):
return args[1]
else:
return args[2]
І в шаблоні:
{% load uapluralize %}
{{ m.comments_count|uapluralize:"коментар,коментарі,коментарів" }}
Підписатися на:
Дописи (Atom)