Пишем движок блога на Python + Django
Допустим, вы хотите написать веб-приложение. Пусть это будет движок для блога.
На PHP надо написать, как приложение будет сохранять в базу данных переданные ему данные (в админке) и отображать их для пользователя. А так же закрыть уязвимости.
Представьте, если не нужно писать код для обращения с базой данных. И не надо самому изобретать функции обработки шаблонов. А так же уязвимости не возникают.
Это не мечта, это Django. Фреймворк для создания веб-приложений на простом, но мощном языке
Python. Попробуем?
Для начала установим Python версии выше 2.3. Потом скачаем Django с официального сайта. Не ставьте из убунтовских репозиториев, а то придётся делать лишние движения типа изменений PATH и добавления прав запуска для скриптов. Скачали, распаковали,
sudo python setup.py install
сделали. Готово! Можно приступать.
Создаём проект и приложение. (Проект может содержать несколько приложений, а приложение можно копировать в разные проекты. Понятно?) Мы делаем личный блог. Назовём проект vasyasite, а приложение blog.
django-admin.py startproject vasyasite
cd vasyasite
django-admin.py startapp blog
Отлично. Мы готовы, можно протестировать встроенный сервер...
Так, я сказал "встроенный сервер"? Да, Django предоставляет разработчикам сервер для тестирования, написанный на Python. (Где вы ещё видели такую заботу о разработчиках?)
python manage.py runserver
Теперь по адресу
http://127.0.0.1:8000/ находится проект vasyasite. Там сейчас только страница с сообщением о том, что Django отлично работает. Ctrl+C его, да! Пока нам сервер не понадобится. Создадим в папке проекта папки templates и media.
Надо бы настроить проект, для этого редактируем settings.py. Мы будем использовать SQLite для баз данных - это просто. Прописываем 'sqlite3' в DATABASE_ENGINE и путь к файлу в DATABASE_NAME. У меня '/home/lol2fast4u/vasyasite/blog.db'. Если такого файла нет - он автоматически создаётся. Не забывайте сменить TIME_ZONE на свою (у меня Europe/Moscow) и LANGUAGE_CODE на 'ru-ru'. Сами догадаетесь, куда прописать созданные папки media и templates, конфиг интуитивно понятен. Тем, кто знает английский %) В INSTALLED_APPS надо дописать плагин комментариев(да. он здесь встроенный есть!), админпанель и своё приложение. У меня выглядит так:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'django.contrib.comments',
'vasyasite.blog',
)
Теперь надо создать модели данных. Они представляют из себя простые питоновские классы. Мы пишем простой блог, значит у нас есть категории и посты. У категории есть название, у поста - категория, дата/время, название и содержание. Вот что надо поместить в blog/models.py:
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class Post(models.Model):
category = models.ForeignKey(Category)
name = models.CharField(max_length=100)
datetime = models.DateTimeField('Date published')
content = models.TextField(max_length=100000)
def __unicode__(self):
return self.name
Обратите внимание на функцию __unicode__: она возвращает название объекта в список. Чтобы список можно было человеку почитать, если он зайдёт в интерактивную консоль ( python manage.py shell ).
А теперь (в папке с проэктом) надо запустить python manage.py syncdb - эта команда создаст все нужные базы данных. Поскольку у нас в приложениях прописана авторизация, скрипт попросит придумать логин, е-мейл и пароль администратора.
Теперь настроим админку. В папке приложения (blog) создаём файл admin.py. В него прописываем, с какими объектами можно будет управлять из админки. Вот что у меня:
from vasyasite.blog.models import Category, Post
from django.contrib import admin
admin.site.register([Category, Post])
Осталось написать публичный вид, "морду" блога. Будем использовать шаблоны.
Сначала создаём "виды". Их будет три: главная(все посты), категория(посты одной категории) и один пост.
Редактируем views.py (который в папке приложения). У меня получился такой:
from django.shortcuts import render_to_response
from vasyasite.blog.models import Category, Post
def main(request):
posts = Post.objects.order_by('-id')
categories = Category.objects.order_by('-id')
return render_to_response('index.html', {'posts': posts, 'categories': categories, 'iscomments': 'false'})
def category(request, category_id):
posts = Post.objects.filter(category=category_id).order_by('-id')
categories = Category.objects.order_by('-id')
return render_to_response('index.html', {'posts': posts, 'categories': categories, 'iscomments': 'false'})
def post(request, post_id):
posts = Post.objects.filter(id=post_id)
categories = Category.objects.order_by('-id')
return render_to_response('index.html', {'posts': posts, 'categories': categories, 'iscomments': 'true'})
Так, подождите. Один шаблон для всех видов? Да, это так. Всё прописывается в шаблоне. Я сделал его в своём же генераторе и положил в templates. Теперь надо отредактировать, чтобы было примерно так:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
<head>
<title>Блог Василия Пупкина</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
#header {
background: #edd400;
margin-bottom: 1em;
}
h1 { font: 2em sans-serif; }
h2 { font: 1.2em sans-serif; }
#sidebar {
background: #c4a000;
float: left;
width: 10em;
display: inline;
margin-left: 1em;
}
#content {
margin-left: 12em;
margin-right: 1em;
}
.post {
background: #c4a000;
padding: 1em;
margin: 1em 0em 1em 0em;
}
.meta {
border: 0.2em dotted #edd400;
margin: 0.1em;
}
#footer {
background: #edd400;
clear: both;
}
</style>
</head>
<body>
<div id="header">
<h1><a href="/">Блог Василия Пупкина</a></h1>
<h2>Работает на Django</h2>
</div>
<div id="sidebar">
Категории:
<ul>
{% for category in categories %}
<li><a href="/category/{{ category.id }}">{{ category.name }}</a></li>
{% endfor %}
</ul>
</div>
<div id="content">
{% for post in posts %}
<div class="post">
<div class="meta">{{ post.datetime }} <a href="/category/{{ post.category.id
}}">{{ post.category.name }}</a> → <a href="/post/{{ post.id }}">{{ post.name }}</a></div>
{{ post.content }}
{% ifequal iscomments 'true' %}
{% load comments %}
{% get_comment_list for post as allcomments %}
{% for acomment in allcomments %}
<div class="meta"><a href="{{ acomment.user_url }}">{{ acomment.user_name }}
</a>: {{ acomment.comment }}</div>
{% endfor %}
<div class="meta">{% render_comment_form for post %}</div>
{% endifequal %}
</div>
{% endfor %}
</div>
<div id="footer">
<p>Разметка от <a href="http://myfreeweb.ru">MyFreeWeb.ru</a></p>
</div>
</body>
</html>
Заметили, что в шаблоне мы указали URL'ы, которых мы нигде больше не указывали? Самое время их указать. Открываем urls.py (в директории проэкта). Раскомментируем строчки для админпанели и добавляем свои для видов. А ещё для комментариев одну. Получается что-то такое:
urlpatterns = patterns('vasyasite.blog.views',
(r'^$', 'main'),
(r'^category/(?P<category_id>\d+)/$', 'category'),
(r'^post/(?P<post_id>\d+)/$', 'post'),
(r'^admin/(.*)', admin.site.root),
(r'^comments/', include('django.contrib.comments.urls')),
)
Активируем сервер, заходим на
http://127.0.0.1:8000/ и получаем ошибку - скрипт не может взять посты т.к. мы их не писали! Заходим в админку
http://127.0.0.1:8000/admin, логинимся (помните, указывали логин и пароль, когда syncdb спрашивал?). Интерфейс понятный :) Создаём категорию и пост. Заходим обратно на
http://127.0.0.1:8000/ и видим... Ура!!! Движок работает. Можно рассказывать друзьям, "какой я крутой" и вести блог.

Домашнее задание: прикрутить
RSS и
комментарии IntenseDebate.
P.S. Читайте официальную документацию!