About Blog Dev | Alfa Romeo SZ Conkeror wishlist

All articles, tagged with “django”

Расположение файлов в проектах Django

Последнее время мне всё более и более странным (я бы даже сказал “недальновидным”) кажется решение авторов оригинального туториала по Джанге показывать именно такой формат расположения файлов в джанге (и уж тем более то, какой sys.path они там используют): в туториале все файлики, созданные с помощью startproject, лежат в одной директории вместе с приложениями. Соответственно, все импорты выглядят как from someproject.someapp import views.

Мне понятно, откуда ноги растут — на деле у них все приложения лежат в sys.path, и потому импортируют они оттуда как from someapp import views, а проект — это лишь настройки да корневой конфиг урлов. Тогда можно родительскую для всех проектов директорию положить в sys.path, и менять только DJANGO_SETTINGS_MODULE. Но в любом случае одним интерпретатором питона для двух джанговских проектов не обойдёшься (спасибо этому самому DJANGO_SETTINGS_MODULE), а способность к лёгкому созданию дистрибутива и его распространению страдает порядочно (что особенно важно для опенсорсовых проектов).

Поэтому мне значительно больше нравится другой подход к делу, который я применяю во всех своих проектах, в том числе и в Byteflow:

project/
  apps/        # собственно приложения
  template/    # шаблоны
  static/      # статические файлы — картинки оформления, стили, JS
  media/       # файлики, загруженные пользователями, не версионируется
  locale/      # переводы
  compat/      # тут библиотеки типа django-atom
  manage.py    # файлы, относящиеся к описанию проекта
  settings.py
  urls.py
  ...

При этом в sys.path добавляется сама директория проекта, DJANGO_SETTINGS_MODULE становится равен settings, а в settings.py двумя строками кода в sys.path добавляется и apps/ с compat/1. В результате все импорты простые и не содержат имени проекта (что тупо хотя бы потому, что я не могу склонировать проект рядом и поэкспериментировать в нём из-за того, что будут проблемы с импортами), а проект становится достаточно независимой вещью, которая для разворачивания на каком-то сервере требует только Джангу и библиотеки, которые достаточно распространённые и/или большие для того, чтобы не включать их в проект.

1

Как это делается, можно увидеть в settings.py у Byteflow.

Фичи Django 1.0

Джеймс Беннет пару дней назад опубликовал список фич, которые важны для релиза Django 1.0, по причине того, что они очень большие и важные, либо того что они простые, маленькие и порядочно улучшают/облегчают использование в обычных случаях, либо (менее важно) они заметно нарушают обратную совместимость и было бы неплохо их интегрировать заранее.

 continue reading

QS-RF

Сегодня про это пишут все, но я всё равно не могу промолчать. :-)

Ветку разработки queryset-refactoring смержили в транк Django, что означает приход порядочной толпы приятностей. ;-) Мне лично очень нравится возможность посмотреть SQL до выполнения собственно запроса (QuerySet.query.as_sql()), ну и логично работающую фильтрацию по одной и той же таблице, хорошо описанную Иваном. Ну и ещё долгожданное многими наследование моделей.

Отличные новости, в общем! :-)

render_to improved

[UPD от 12 ночи]

Чуть больше года назад, когда меня окончательно задолбало писать render_to_response c кучей параметров, я себе написал маленький декоратор render_to, который заметно уменьшал количество писанины.

Но вот не так давно обсуждали его в джаббер-конференции pythonua@c.j.r (кстати, официальная конференция python.com.ua), где появилась идея слегка его проапгрейдить до возможности задавать темплейт из view (когда одна вью может выдавать различные странички). В принципе, идея усложнения декоратора мне не особенно нравится (да и потом, кому надо — может переделать себе, благо несложно), но по размышлении я увидел, что особенного усложнения нету, плюс сохраняется обратная совместимость полностью (что важно, потому как мне есть и где использовать новую фичу, но не очень хочется ломать все вьюхи, использующие старую версию ;).

 continue reading

ImprovedImageField

В процессе работы над одним проектом я в очередной раз столкнулся с тем, что джанговский ImageField меня ну никак не устраивает — в нём отсутствует возможность ресайза при аплоаде, некак загружать картинки в разные директории1, кроме как по дате, ну и динамически назвать файлик2 тоже нельзя.

 continue reading

Дебаг Джанги

Как проходит дебаг джанги обычно? В 90% случаев хватает внимательно изучить желтенький джанговский трейсбек ошибки, со всеми переменными и кодом, ещё в 9% хватает расставить print‘ы, а в совсем запущенных случаях приходит на помощь winpdb.

Но после одной отличной новости можно значительно облегчить себе жизнь - перестать расставлять print’ы, перестать изучать трейсбеки досконально и отказаться от удалённого дебаггера, заодно показав язык Pylons’ам, в которых такая штука есть давно. :-)

Вообще я этот пост прочёл и пролистал, когда он появился неделю назад. А тут случайно наткнулся на него ещё раз и решил попробовать. Фантастика! :-) Встречайте - консоль прямо в трейсбеке. :) Я сделал скрин (250 кб) моих первых шагов в неизведанное. ;-)

Рекомендую. Офигенская штука. Сам по себе werkzeug небольшой, стартует быстро (быстрее джанги), проблем не вызывает и вообще… просто красота теперь. :)

Пользователь и его профиль

Известная штука, что у Django есть статическая (неизменяемая официально поощряемыми путями) модель User и костыль для дополнительных полей (которые может каким-либо образом использовать приложение) в виде настройки USER_PROFILE, указывающей на модельку-профиль. В результате использования такого костыля, если не делать дополнительных телодвижений, количество запросов возрастает (пример для данного блога, где каждому комментирующему ставится ссылка на его сайт) на число комментариев (даже не комментировавших, а комментариев!).

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

Потому, после продолжительных колебаний и сомнений, я решил сделать всё радикальнее - удалить всю модель UserProfile, применив вместо неё monkey patching к стандартной модели:

User.add_to_class('site', models.URLField(verify_exists=False, blank=True))
User.add_to_class('email_new', models.EmailField(blank=True))

User._meta.admin.fields += (
    ('Byteflow Extensions', {'fields': ('site', 'email_new')}),
    )

Конечно, главная проблема здесь - это то, что способ совершенно не стандартный и вряд ли кто-то будет ожидать, что табличка auth_user будет меняться. Но такой способ настолько выгоднее и удобнее, что я решил наплевать на эти трудности. :-)

И ещё одно - спасибо Амиту, который и показал конкретно, как это сделать. ;-)

Django performance: Apache vs Nginx - en

Just a week ago I have compared performance and stability of nginx working with Django through mod_wsgi and fastcgi. Comparison revealed that performance with fast local DB (i.e. time of DB work is negligibly small) is almost identical and all the difference is in used resources.

Today at last I have time to look, what will be, when database is located at other computer and WiFi connection between application and DB worsening situation. :-) I.e. sense of my today’s actions is looking at situation, when DB is slow (this is interesting for me after Manlio’s commentary in previous post). Additionally I wanted to look at Apache’s behavior.

Before doing that I runned lightweight test (ab -n 100 -c 20) on Apache (with local database), which showed up that Apache don’t want to use my two cores. :-( Nor prefork, neither worker don’t used second core and time between requests was around 28 ms, which is two times to nginx’ 14 ms. Logic thoughts said that heavy-weight Apache in any case is slower than nginx — second core will not improve performance in two times (so says nginx’ 24 ms when working with one core :-).

Further PostgreSQL was launched at another laptop. Apache was tested in both versions, prefork and worker and displayed no difference, so I’ve stopped on worker.

First — ab -n 1000 -c 20:

  • Apache — ~37 ms. Very stable, difference in time between 5 runs was lesser than 1 ms.
  • nginx + mod_wsgi — ~50 ms. Expected (as Manlio said, nginx is blocked while working with application, which is blocked by request to DB).
  • nginx + fastcgi prefork — ~28 ms. I can’t believe it is so faster than Apache! :-)

Second test — ab -n 3000 -c 500 — is not very distinguished from first. Apache and fastcgi — same result, mod_wsgi raised to 55 ms.

At that moment I thought that mod_wsgi is only suited for application without database (or when delays for its work is negligibly small). But, thought over, I made knight’s move — raised number of workers in nginx. :-) With 16 workers (tested after — 8 is enough) and 500 concurrent connections delay between answers is 28 ms. Now I can believe in fastcgi result and Apache is heavy and fat, as usual. ;-) Thought, every nginx’ process, which works with Django, eats around 15 mb of RAM. However apache and fastcgi (threaded, forked) want bigger amount of memory.

Everyone can do summary for himself, the only one thing I can say unambiguously — nginx + mod_wsgi is very interesting combination.

Django performance: Apache vs Nginx

Неделю назад я сравнивал производительность и устойчивость работы nginx’а с Django с помощью mod_wsgi и fastcgi. Сравнение показало, что скорость работы при наличии быстрой локальной (читай - практически не оказывающей влияние) БД практически не отличается, отличается только количество используемых ресурсов.

А сегодня я наконец-то собрался посмотреть, что же будет, когда база данных находится на другом компе, а связь по wifi между веб-сервером и БД усугубляет проблему. :-) То есть весь смысл сегодняшних моих мучений - посмотреть на ситуацию с тормозящей базой данных (стало интересно после комментария Манлио). Заодно и хотелось посмотреть, как себя ведёт Apache.

Перед этим я таки запустил пару раз лёгкий тест (ab -n 100 -c 20) на Апач (с локальной базой данных), который показал, что апач не хочет использовать два моих ядра ни в какую. :-( Ни prefork, ни worker не использовали второе ядро и запрос в среднем занимал 28 мс, что в два раза дольше, чем nginx’овый показатель - 14 мс. Логически поразмышляв, можно понять, что тяжёлый Апач в любом случае работает медленнее nginx’а - второе ядро в два раза не ускорит (что и говорит показатель в 24 мс у nginx’а при работе с одним ядром :-).

Дальше PostgreSQL был запущен на другом ноуте. Апач я мерял как в prefork версии, так и в worker.

Первый вариант - ab -n 1000 -c 20:

  • apache - ~37 мс. Стабильно, в пределах 5 запусков разницы не было даже в миллисекунду.
  • nginx + mod_wsgi - ~50 мс. Ожидаемо.
  • nginx + fastcgi prefork - ~28 мс. В мозгу не укладывается, что оно настолько быстрее Апача! :-)

Второй вариант - при ab -n 3000 -c 500 - не слишком отличается. Апач и фастцги - такие же, мод_всги вырос до 55 мс.

В этот момент мне показалось, что mod_wsgi годится только когда нету БД (или задержками на её работу можно пренебречь). Однако, поразмыслив, я сделал ход конём - увеличил количество воркеров в нгинксе. :-) При 16 воркерах (проверено позже - 8 достаточно) и 500 одновременных запросов один отклик приходит в среднем раз в 28 мс. Теперь и результат фастцги укладывается, и апач выглядит толстым и тяжёлым, как обычно. ;-) Правда, каждый процесс nginx’а, работающий с джангой, кушает порядка 15 мегабайт. Хотя это в любом случае меньше, чем апач и fastcgi.

Выводы каждый может сделать сам для себя, но nginx + mod_wsgi однозначно - очень интересная комбинация.

Nginx + Django: mod_wsgi vs FastCGI - en

(Translation of my previous post).

Yesterday I have finally sorted out my trouble with compilation of nginx’ mod_wsgi and got it working (how much means slash in our life ;-).

Configuration to get Django application running is quite simple — django.wsgi, which is used for Apache’s mod_wsgi, fits perfectly. I’ll not describe all configuration, because code is unstable and needs testing and is’s contra-indicated to run it on production now.

Lets do the fun — testing. :-) Simple page, 15 queries (PostgreSQL on same pc), 2 workers for nginx (I have tried 3 and 4 — they both are slighty slower, for 2-4 ms). Two variants of testing queries (ab -n 1000 -c 20 and ab -n 10000 -c 500) and three variants of servers (mod_wsgi, prefork fastcgi, threaded fastcgi). Hardware (this is not so interesting, because performance is interesting only in comparison, but why not to show it?) — Core 2 Duo T7300 and 2 Gb of RAM.

First — ab -n 1000 -c 20 (around of 10-12 runs for every variant):

  • mod_wsgi takes 14.2-14.3 ms per query, quite stable performance
  • prefork fastcgi takes 12.5-16.5 ms (mostly near of 12 ms, but raises from time to time), eats bigger amount of RAM — I have an xmobar1 showing usage of RAM and mod_wsgi has a two-three percents (percent is 20 megs) lesser usage
  • threaded fastcgi takes 24-25 ms per query — it uses only one core of CPU. I have tried to get upstream working in nginx — it works, but uses only 1 process for some reason :-(

I.e. in most cases for such load FastCGI is slighty faster (and uses somewhat bigger amount of resources). But… lets go further? ;)

Second — ab -n 10000 -c 500 (here I got 3-4 runs for every variant):

  • mod_wsgi takes 13-14 ms. Pretty stable result. Each worker consumes 21/15 megs of RAM (VSZ/RSS)
  • prefork fastcgi takes 15.5-17 ms per request, but it runs from 40 to 50 serving instances, each consuming 16-20 VSZ (10-13 RSS) megs of RAM! xmobar says that usage raises up to 50% (by leaps, usually around 45-48%) — compare to 33% for mod_wsgi! Additional 300 mbytes of RAM.
  • threaded fastcgi — most “interesting” variant. With this level of concurrency it just dies. With -c 100 — dies. It lives with -c 50 with slighty lower speed than with -c 20, but process eats near of 300 mb of VSZ.

What I can say here? Lets wait for stable mod_wsgi release! :-) Thanks, Manlio, for this piece of code. :-)

1

xmobar — small statusbar, written on Haskell. Displays system state and other various information