среда, 26 декабря 2007 г.

Django: регистрация новых пользователей или django-registration, часть 1

Раз есть юзеры, значит, их нужно как-то регистрировать :-)

Для этого предназначен django-registration.

Работает так:

  1. юзер по адресу http://ваш_адрес/accounts/register/ заполняет форму с 4 полями: "username", "email address", "password", "password (again)".
  2. юзеру отсылается мыло с линком для активации учётной записи.
  3. юзер кликает линк, учётная запись активируется.
Чекаем код из SVN в проект, в settings.py добавляем опцию
ACCOUNT_ACTIVATION_DAYS = 3 (вместо 3 можете указать своё количество дней, в течение которых юзер может кликнуть на линк для активации), в INSTALLED_APPS добавляем 'registration',
manage.py syncdb
Можно юзать ? В принципе, да :-)

Всё ОК, и документация есть, но в версии из SVN нету шаблонов для примера. Это очень плохо. Мне пришлось прочитать документацию и код, чтобы сделать шаблоны. Чтобы вам не париться с этим, а сразу иметь рабочие примеры, я и пишу этот пост :-)

Я так настраиваю TEMPLATE_DIRS:

TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates'),
)


В каталоге шаблонов делаем подкаталог с названием registration. В нём создаём следующие шаблоны:

------ registration_form.html ------

<form action="." method="POST">
<table>
{{ form }}
</table>
<p><input type="submit" value="Submit"></p>
</form>


Необходимый элемент - {{ form }}. Это форма как раз с теми 4 полями: "username", "email address", "password", "password (again)".

------ activation_email_subject.txt ------

Your registration for {{site}}.

Содержит переменную - {{ site }} (название сайта из админки).
Это тема письма, которое будет выслано после регистрации.

------ activation_email.txt ------

Hello,

Please follow this link to complete your registration on {{ site }}:
http://www.yoursite.com/activate/{{activation_key}}/


You have {{ expiration_days }} days to complete it.


Sincerely,

bla-bla-bla


Это шаблон письма, которое будет выслано новому юзеру для подтверждения регистрации. {{ expiration_days }} задаётся в settings.py, как ACCOUNT_ACTIVATION_DAYS (у меня это 3).

------ registration_complete.html ------

<h1>Confirmation e-mail sent !<br />
Please check your inbox to complete registration :-) </h1>


Этот шаблон выводится сразу после того, как выслано письмо.

------ activate.html ------

<h1>Confirmation e-mail sent !<br />
Please check your inbox to complete registration :-) </h1>


Этот шаблон выводится сразу после того, как выслано письмо.


В принципе, как только вы создадите эти шаблоны, можно сразу тестировать - по адресу http://ваш_адрес/accounts/register/. После подтверждения регистрации смотрите в админке - появился новый юзер :-)

Сразу можно менять эти шаблоны под свой сайт, и юзать. Нормальный вариант !

Там ещё фичи есть, поэтому "часть 1". Наверное, ещё будут посты на эту тему, так что предусматриваю заранее :-)

четверг, 20 декабря 2007 г.

Миграции в Django

В RoR имеется концепция миграций: все изменения в моделях фиксируются определённым образом, чтобы потом можно было проапдейтить и development и production БД _автоматически_.

Django не умеет синхронизировать изменения моделей с БД (по крайней мере, на момент написания этого текста) :-(

Отсюда проблема - как быть ?

Вот так - Django Evolution.

Как юзать ?

В общем-то, элементарно. Но, имеются тонкости: если у вас ещё не было _ни одного_ syncdb с моделью, то эта система не сработает. Поэтому подключить к проекту на этапе, когда нет ни одной модели (в самом начале проекта), не получится. Я об этом упоминаю отдельно, чтобы вы не наступали на ненужные грабли.

Теперь, по шагам, для нового проекта:

1) создаём какие-то модели (модель)
2) делаем manage.py syncdb
3) забираем Django Evolution из SVN: svn checkout http://django-evolution.googlecode.com/svn/trunk/ django-evolution-read-only
4) копируем подкаталог django_evolution в свой проект (или, если есть возможность, делаем симлинк)
5) в settings.py в INSTALLED_APPS добавляем django_evolution
6) делаем новый подкаталог для всех app, которые в проекте - evolutions, в нём создаём файл "__init__.py"
7) после изменений в модели делаем manage.py syncdb, видим "Project signature has changed - an evolution is required"
8) делаем manage.py evolve --hint, видим что-то вроде этого:

#----- Evolution for website
from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
DeleteField('Poll', 'pub_date')
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --hint --execute' to apply evolution.

9) теперь копируем весь текст между строками с #-----, т.е. в данном случае:

from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
DeleteField('Poll', 'pub_date')
]

в файл с информативным названием(в данном случае удаляется поле pub_date в модели Poll, называем delete_poll_pub_date.py) в каталог evolutions для app, в котором изменения. У меня app называется website, поэтому получается так:

/website
/evolutions
delete_poll_pub_date.py
__init__.py
не забыли создать __init__.py до этого ?

10) теперь добавляем в файл evolutions/__init__.py такую строчку:

SEQUENCE = ['delete_poll_pub_date']

т.е., в файле evolutions/__init__.py задаётся последовательность модификаций БД.

11) пишем

manage.py evolve --execute

выводится вопрос, отвечаем yes (чтобы всё проходило без вопросов, нужно добавить к команде ключ --noinput, но лучше оставить без --noinput, чтобы было похоже на Terminator 3 :-) ).

В результате имеем: Evolution successful. Т.е. прошёл апдейт структуры БД. Если ещё раз набрать manage.py evolve --execute, выведется "No evolution required."

Вот таким образом это всё работает.

Копируем на production все изменения в нашем коде, включая все файлы evolutions, и там запускаем manage.py evolve --execute.

Конечно, это не полный автомат - но согласитесь, намного лучше, чем ничего. Я думаю, что можно усовершенствовать скрипт, чтобы он сам создавал необходимое в evolutions, но самому некогда.

Насчёт багов пока не в курсе, так что про бекапы не забываем :-)
Читаем полную доку либо тут, либо в docs, который пришёл с svn.

Успехов !

пятница, 14 декабря 2007 г.

Наследование шаблонов в Django - пути.

Путь к шаблонам в теге {% extends %} _всегда_ отсчитывается от корня каталога шаблонов, определённого в TEMPLATE_DIRS.

Поэтому, морочить голову вещами типа "../../somedir/somefile" не нужно. Во-первых, это не сработает, во-вторых, можно и без "../../" :-)

Просто нужно иметь в виду, что путь начинается с корня, и всё.

Трудно забывать привычки :-)

четверг, 13 декабря 2007 г.

Происшествия Microsoft

Долго не писал, молчание - золото :-)

Никак не могу отписаться от рассылки Microsoft "Бюллетень-молния TechNet" - уже не помню, когда и зачем подписался. Но отписаться просто нереально, в отличие от других рассылок. Но не об этом сейчас.

Получил очередное сообщение, и, перед тем, как удалить, решил посмотреть, что же там пришло.

В первом же абзаце:

"...А теперь я каждый раз сталкиваюсь с проблемой, что даже простое перечисление «через запятую» наиболее интересных происшествий в области ИТ и Microsoft может по размерам выйти далеко за пределы, допустимые для одной колонки."


Ключевое слово здесь - "происшествие". Смотрим в словарь:
Событие, приключение, случай, что-н., нарушающее нормальный порядок, обычный ход вещей.
(более подробное описание под ссылкой).

Очевидно, автору хотелось иметь в виду "событие". Но, я думаю, что это оговорка по Фрейду :-)

Думаю, не нужно тут объяснять, почему рассылку с предложениями продуктов не стоит начинать текстом о собственных проблемах :-)

У Microsoft мне нравятся несколько программ, но то, как они делают многие вещи, просто удивляет, мягко говоря.

Пример хорошей, "правильной" (с моей точки зрения) компании - 37signals. Я подписан на их рассылку, но она настолько необременительна (по-моему, получил за несколько месяцев 2 письма), и настолько интересна, что стоит того, чтобы её получать.

Да здравствуют приятные события !