Захотелось мне поведать как использовать связь ManyToMany, начал я значит писать пост, но так как я хотел его детализировать то он слишком разросся... И я решил сначала написать пост о том, как создавать первый проект и приложение на Django, чтобы потом ссылаться сюда.
-- начинал я этот пост писать еще в том году, да все руки не доходили его закончить, спасибо vasa_c за терпение
Допустим, что имя проекта у нас будет "myproject":
cd /www
django-admin.py startproject myproject
Теперь создайте себе новую БД "myproject":
CREATE DATABASE `myproject` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
И отредактируйте "/www/myproject/settings.py", заменив только соответствующие части:
# ~*~ coding: utf-8 ~*~
...
# Настройки БД
DATABASE_ENGINE = 'mysql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'myproject' # Or path to database file if using sqlite3.
DATABASE_USER = 'username' # Not used with sqlite3.
DATABASE_PASSWORD = 'password' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
...
# Путь до каталога, где лежат наши медиа файлы (css, js, images)
MEDIA_ROOT = '/www/myproject/static/'
...
# URL медиа файлов (css, js, images)
MEDIA_URL = '/'
...
# URL медиа файлов админки (css, js, images, etc)
ADMIN_MEDIA_PREFIX = '/admin-media/'
...
# Путь до каталога с шаблонами
TEMPLATE_DIRS = (
"/www/myproject/blog/templates",
)
...
# Установленные приложения в нашем проекте
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'myproject.blog',
)
# в конец добавлено две строки, первая подключает джанговскую админку,
# а второе наше приложение, которое мы ниже опишем
Для чего я ставлю в начале строки "#~~ coding: utf-8 ~~" читайте тут.
Создаем наше первое приложение
После того, как вы создали проект, надо создать приложение, если у вас проект состоит из одного приложения - можете его назвать "main".
Создаем приложение "blog":
cd /www/myproject
python manage.py startapp blog
Файл модели
Теперь перейдем к разработке модели нашего приложения, отредактируем "/www/myproject/blog/models.py".
У нас будет пока одна сущность, это Посты в Блоге:
# ~*~ coding: utf-8 ~*~
# импортируем класс модели
from django.db import models
# и админки
from django.contrib import admin
'''
Blog posts
'''
class Post(models.Model):
# название поста
title = models.CharField(max_length=100)
# содержимое поста
text = models.TextField()
# функция необходима для того, чтобы при выводе объекта Post
# как строки выводился вместо этого его title
def __unicode__(self):
return self.title;
'''
Класс для админки, тут будут дополнительные атрибуты необходимые для админки
'''
class PostAdmin(admin.ModelAdmin):
# в таблице списка постов выводить только колонку title, если вы добавите еще одно имя поля, то и оно выведется
list_display = ('title',)
# связываем эту модель с моделью PostAdmin
admin.site.register(Post, PostAdmin)
Вы можете все что связано с админкой вынести в admins.py и импортировать его, чтобы избавится от лишнего кода
После создания файла моделей, вам необходимо запустить синхронизацию с БД, для того чтобы создались структуры данных:
cd /www/myproject
python manage.py syncdb
Для более детального изучения команд manage.py введите:
python manage.py help syncdb
Вы так же можете создавать свои команды, но об этом поговорим не в этот раз.
syncdb создаст таблицы в вашей БД, а также при первой инициализации попросит создать рутовую учетную запись для вашего проекта в django (это будет админский аккаунт):
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table django_admin_log
Creating table blog_post
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'root'):
E-mail address: mail@example.com
Password:
Password (again):
Superuser created successfully.
Installing index for auth.Permission model
Installing index for auth.Message model
Installing index for admin.LogEntry model
Когда вы создадите новый класс модели вам будет необходимо вновь запустить syncdb.
Если вы внесли изменения в уже синхронизированное приложение, а именно в его модель, то syncdb НЕ внесет их в вашу БД, для этого используйте sqlall и другие sql* комманды:
Или попробуйте расширение для Django Django Evolution (для этого необходимо его установить в вашу систему и добавить в INSTALLED_APPS - "django_evolution").
Файл урлов
Для навигации по вашему проекту вам нужен роутер (URL диспетчер).
Отредактируем "/www/myproject/urls.py":
# ~*~ coding: utf-8 ~*~
# импортируем админку
from django.contrib import admin
# Makes the patterns() function available
from django.conf.urls.defaults import *
# импортируем наши вьюхи (см. ниже описание файла вьюх)
from myproject.blog.views import main_page, get_post
# Above we used admin.autodiscover() to automatically load the INSTALLED_APPS admin.py modules
admin.autodiscover()
urlpatterns = patterns('',
# Если ничего не введено, то отдаем управление mainpage вьюхе
(r'^$', main_page),
# Если передан id поста, то отдаем управление get_post вьюхе
(r'^post/([0-9]{1,5})', get_post),
# Если введен /admin/, то идем в админку
(r'^admin/', include(admin.site.urls)),
)
Вы конечно можете отредактировать локальный для приложения "blog" - urls.py ("/www/myproject/blog/urls.py"), но тогда вам надо будет импортировать "/www/myproject/blog/urls.py" в корневом "urls.py". Либо вы можете его определить в settings.py (ROOT_URLCONF).
Файл вьюхи
Ту роль, которую играет "Controller" в MVC, в Django играет роль View. Почему это так читайте тут.
Отредактируем "/www/myproject/blog/views.py":
# ~*~ coding: utf-8 ~*~
# функция генерирующая 404 страницу
from django.http import Http404
# функция отрисовки страницы, принимающая путь до шаблона и данные помещенные в шаблон
from django.shortcuts import render_to_response
# наша модель
from myproject.blog.models import Post
def main_page (request):
# Получаем список постов
posts = Post.objects.all()
# отрисовываем
return render_to_response('list.html', {"posts": posts})
def get_post (request, post_id):
try:
# выбираем конкретный пост, pk - primary key
post = Post.objects.get(pk=post_id)
except Post.DoesNotExist:
# если такого поста нет, то генерируем 404
raise Http404
# отрисовываем
return render_to_response('single.html', {"title": post.title, "text": post.text})
Вывод в шаблоне
В Django очень мощный и гибкий шаблонизатор, у него даже есть аналог на PHP - Twig, что говорит о его удобстве (был бы неудобным - не копировали бы), хотя Twig по слухам сильно хуже.
Однако, есть более крутой шаблонизатор для Django - Jinja2, с более высокой производительностью и более гибкими возможностями. Описывать Jinja я не буду, ведь не это цель сего поста, поэтому делюсь только ссылочками:
{% extends "base.html" %}
{% block title %}List!{% endblock %}
{% block content %}
<ul style="list-style-type:none">
{% for post in posts %}
<li style="padding-left:10px;{% if forloop.counter0|divisibleby:"4" %}background-color:#E1F3C9{% endif %}">
<a href="/post/{{ post.id }}/">{{ post.title }}</a>
<p>{{ post.text }}</p>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
Шаблон вывода одной записи single.html:
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<div>
{{ text }}
</div>
{% endblock %}
Nginx
Теперь настроим Nginx для того, чтобы запуская "manage.py runserver" нам не прописывать порт в URL и чтобы использовать нормальное имя хоста, хотя вы может вполне без это обойтись.
Но я очень рекомендую использовать Nginx.
# в новых версиях nginx можно послать сигнал
nginx -s reload
# или для ubuntu/debian через скрипт инициализации
service nginx restart
/etc/init.d/nginx restart
# или для freebsd
/usr/local/etc/rc.d/nginx restart
Запускаем веб-сервер проекта на 8001 порту, так как мы туда будем проксировать из Nginx:
cd /www/myproject
python manage.py runserver 8001
Теперь зайдите в админку (http://myproject.loc/admin/), введите вашу "root" учетку, которую создавали при syncdb.
Вот мы и познакомились с первым приложение на Django, как я и обещал в начале этого поста следующая статья будет о ManyToMany, где мы подключим к нашему "Блогу" возможность создавать и выводить теги, а также расскажу более полно о возможностях моделях и ORM, View и о URL диспетере.
P.S. Пост дописывал в торопях, если найдете любые ошибки - обязательно отпишитесь в комментарии, спасибо!
ну я не только писал для "убунты", поэтому судо - лишнее. И вообще она не относится к делу, кто как работает. Вообще возможно кто-то под www создает проект и ему точно незачем sudo :)
Разве не правильнее будет поставить django из пакетной системы, как и все остальное?
aptitude install python-django (в squeeze сейчас 1.1.1-5)
cd /usr/ports/www/py-django ; make ; make install
Вот именно что "1.1.1-5", а сейчас есть 1.2, в этом вся проблема пакетов... С портами все конечно лучше, но всеравно не то. Лично я вообще использую версию из транка
P.S. textarea у коммента какая-то странная, в FF при размере окна 800×480 на моем eeepc 701 длинные строки не переносятся
Ага, тоже заметил, хотя у меня на нетбуке 1366x768 (заметил из-за увеличения шрифта в броузере), сенк, поправлю
Сам недавно сел за официальный туториал по Django. В документации к версии 1.2 есть небольшие отличия от того что Вы описываете, а так все классно. Отдельное спасибо за конфиг Nginx-а =)
Привет! Классный туториал, спасибо за труды!)
Есть пара вопросов:
1) если меняются настройки в проекте или в других файлах (urls.py, views.py), нужно ли перезагружать апач? кажется без перезагрузки ничего не меняется
2) сделал все по твоей инструкции, админка (/admin/) почему-то не открывается пишет 404 ошибку и {'path': u'admin/'} при этом морда сайта грузится и выводит List.html
В settings.py задал MEDIA_ROOT, включающий путь к папке media; ADMIN_MEDIA_PREFIX='/media/'; MEDIA_URL = '/'.
Далее, в шаблоне подключаю css-файл. Испробовал много разных вариантов, но ни один не срабатывает...
На сколько я понимаю, назначать alias надо в настройках apache? Я еще не настраивал сервер, а работаю со встроенным джанговским. Полагал, что для работы с ним настраивать ничего не надо... Или я ошибаюсь
?
Я отдаю статику через nginx и не встречался с вопросом как отдать статику через runserver. Думаю это возможно, но это совсем не его задача, так что лучше воспользуйтесь nginx или другим вебсервером предназначенный для этих целей
За статью спасибо! У меня такой вопрос: Хочу на всех страницах выводить список записей, в боковом меню. Не могу понять как это реализовать. Получается вывести только для главной, а на других страницах менюшка уже не отображается. Писать функцию для каждой страницы не хочется. Может кто-то порекомендует красивое решение? Заранее спасибо.
Комментарии
Спасибо!
Ты охуен!
Расставь sudo где надо, не все такие хардкорные.
Разве не правильнее будет поставить django из пакетной системы,
как и все остальное?
aptitude install python-django (в squeeze сейчас 1.1.1-5)
cd /usr/ports/www/py-django ; make ; make install
P.S. textarea у коммента какая-то странная, в FF при размере окна
800x480 на моем eeepc 701 длинные строки не переносятся
vasa_c, спасибо, ты тоже)
ну я не только писал для "убунты", поэтому судо - лишнее. И вообще она не относится к делу, кто как работает. Вообще возможно кто-то под www создает проект и ему точно незачем sudo :)
bappoy,
Вот именно что "1.1.1-5", а сейчас есть 1.2, в этом вся проблема пакетов... С портами все конечно лучше, но всеравно не то. Лично я вообще использую версию из транка
Ага, тоже заметил, хотя у меня на нетбуке 1366x768 (заметил из-за увеличения шрифта в броузере), сенк, поправлю
эта, а если в роутере ни один шаблон не совпал и я хочу передать управление другому роутеру (Database)?
думаю несложно догадаться, кто это пишет)
Сам недавно сел за официальный туториал по Django. В документации к версии 1.2 есть небольшие отличия от того что Вы описываете, а так все классно. Отдельное спасибо за конфиг Nginx-а =)
Добавь в конце
А в myurls.py будет твой роутер
xoma, вам спасибо за лестный фидбек )
bappoy, поправил верстку формы комментирования в блоге, стало лучше?
да, стало намного лучше, большое спасибо! а еще кнопку "отправить" не видно, она появляется только при нажатии на tab, при этом форма съезжает влево.y
Кнопку поправил, сейчас лучше? :)
Ага, теперь все на месте, еще раз спасибо!
Тебе спасибо!
Привет! Классный туториал, спасибо за труды!)
Есть пара вопросов:
1) если меняются настройки в проекте или в других файлах (urls.py, views.py), нужно ли перезагружать апач? кажется без перезагрузки ничего не меняется
2) сделал все по твоей инструкции, админка (/admin/) почему-то не открывается пишет 404 ошибку и {'path': u'admin/'} при этом морда сайта грузится и выводит List.html
Alexander, откажитесь от использования apache, используйте для разработки runserver, а для продакшена - nginx+tornado
Хорошая статья, но есть вопросы:
1) Не получается подключить css-файлы.
2) Можете описать настройку apache для работы с django?
Далее, в шаблоне подключаю css-файл. Испробовал много разных вариантов, но ни один не срабатывает...
На сколько я понимаю, назначать alias надо в настройках apache? Я еще не настраивал сервер, а работаю со встроенным джанговским. Полагал, что для работы с ним настраивать ничего не надо... Или я ошибаюсь
?
Я отдаю статику через nginx и не встречался с вопросом как отдать статику через runserver. Думаю это возможно, но это совсем не его задача, так что лучше воспользуйтесь nginx или другим вебсервером предназначенный для этих целей
Попробую настроить. Спасибо.
it's work! :D
Sinkler, конгратулейшенс!
За статью спасибо! У меня такой вопрос: Хочу на всех страницах выводить список записей, в боковом меню. Не могу понять как это реализовать. Получается вывести только для главной, а на других страницах менюшка уже не отображается. Писать функцию для каждой страницы не хочется. Может кто-то порекомендует красивое решение? Заранее спасибо.
Все достаточно просто, вы можете добавить в TEMPLATE_CONTEXT_PROCESSORS свой контекс, который будет доступен в любом месте.
Два других варианта выборочны:
Пример:
Спасибо, помогло =)
А обещанную статью про manytomany так и не написал …
Оставьте свой комментарий