Немного теории
Модель в Django это описание сущностей приложения при помощи специального синтаксиса, например у нас может быть сущность пользователь с полями логин, пароль, адрес электропочты, дата рождения и сущность запись в блоге с полями заголовок, содержание и ссылкой на пользователя, который опубликовал запись.
Модель описывается как класс, унаследованный от Model, поля объекта описываются путем присвоения значений из класса Model, каждое из значений означает один из допустимых типов полей.
Для примера опишем указанные выше сущности:
#сущность пользователь
class User (models.Model):
login = models.CharField(max_length=50)
password = models.CharField(max_length=50)
email = models.EmailField()
age = models.DateField()
#сущность запись в блоге
class Post (models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
poster = models.ForeignKey('User')
Рассмотрим что же мы написали.
Запись вида
login = CharField(max_length=50) означает, что сущность пользователь обладает свойством логин, которое представлено строкой символов максимальной длиной 50, просто не правда ли?
EmailField это поле для хранения адреса электропочты, DateField — для хранения даты, TextField для хранение текста, а ForeignKey определяет ссылку poster на объект класса пользователь.
По описанию моделей Django сможет разработает для нас схему базы данных, создаст административный интерфейс и валидаторы. Мы написали всего 10 строчек кода, а получили достаточно много функций, это одна из основных идей рассматриваемого фреймворка — написание приложения с использованием меньшего количества кода.
SQL-код сгенерированный Django по описанным моделям:
CREATE TABLE `default_post` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`title` varchar(100) NOT NULL,
`body` longtext NOT NULL,
`poster_id` integer NOT NULL
)
;
CREATE TABLE `default_user` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`login` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`email` varchar(75) NOT NULL,
`age` date NOT NULL
)
;
ALTER TABLE `default_post` ADD CONSTRAINT poster_id_refs_id_3b3164d6
FOREIGN KEY (`poster_id`) REFERENCES `default_user` (`id`);
Приложение
Для завершения настройки нашего проекта создадим приложение — осмысленная часть нашего проекта выполняющая какие-либо действия. В Zend Framework можно найти аналогичный механизм —
модуль.
Пока не вижу необходимости разбивать наш проект на приложения, поэтому ограничимся одним и назовем его default. Запустите эту команду находясь в директории coblogs
python manage.py startapp default
Итак, мы получили новую директорию default, в ней вы найдете файл models.py, который содержит описания моделей, весь код описанный далее содержится в этом файле.
Так же необходимо отредактировать settings.py, включив default в список установленных приложений
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'coblog.default'
)
Модели
Напомню, что мы создаем сервис коллективных блогов с визуальным/wiki редактором, тегами, кармой и рейтингом постов и комментариев. Попробуем создать костяк моделей проекта, постепенно расширяя его при необходимости.
Первая модель — наш дорогой и любимый пользователь, но описывать её не нужно в Django есть встроенный механизм аутентификации включающий модель User.
Поля «стандартного пользователя»:
- username
- имя пользователя (логин), обязательное поле, не более 30 букв, цифр и знаков подчеркивания.
- first_name
- имя пользователя (по паспорту ;), опционально, не более 30 символов.
- last_name
- фамилия пользователя, опционально, не более 30 символов.
- email
- электропочта.
- password
- хеш пароля, обязательное поле, метод set_password поможет установить хэш по паролю.
- is_staff
- определяет, может ли пользователь использовать админку.
- is_active
- определяет, не заблокирован ли пользователь (true — не заблокирован).
- is_superuser
- если true, то пользователь имеет все возможные права.
- last_login
- дата и время последнего входа на сайт.
- date_joined
- дата и время создания аккаунта.
Кроме полей есть полезные стандартные методы, описанные в
руководстве.
Для пользователя в нашем проекте не хватает одного поля — кармы, добавим его, воспользовавшись механизмом профайлов:
# -*- coding: utf8 -*- укажем кодировку этого файла
#подлючение механизма моделей
from django.db import models
#подключение стандартной модели пользователя
from django.contrib.auth.models import User
import math
class Profile(models.Model):
#Порог уровня изменения кармы см. get_karma_delta
KARMA_DELTA_THRESHOLD = 10
#ссылка на стандратную модель пользователя
user = models.ForeignKey(User, unique=True)
__karma = models.IntegerField(default=0)
def inc_karma(self, delta):
"""Увеличивает(или уменьшает) карму пользователя на delta"""
self.__karma += delta
def get_karma(self):
"""Возвращает карму пользователя"""
return self.__karma
def get_karma_delta(self):
"""
Возвращает на какое значение пользователь может
изменить карму другого пользователя
"""
if self.__karma == 0:
return 1
else:
return math.ceil(self.__karma/self.KARMA_DELTA_THRESHOLD)
#Данный класс нужен для появления модели в административном интерфейсе
#(об этом в следующий раз)
class Admin:
pass
Для подключения нашего профиля добавим строку в settings.py:
AUTH_PROFILE_MODULE = "default.profile"
теперь профиль пользователя доступен при помощи метода get_profile().
Следующие модели — блог (пока содержит только название и описание) и запись в блоге:
class Blog(models.Model):
caption = models.CharField(max_length=50)
description = models.TextField()
created = models.DateTimeField(auto_now_add=True)
#функция __unicode__ определяет строковое представление объекта
def __unicode__(self):
return self.caption
class Admin:
pass
class Post(models.Model):
""" Запись в блоге """
#ссылка на блог в котором опубликована запись
blog = models.ForeignKey(Blog)
#ссылка на пользователя опубликовавшего запись
poster = models.ForeignKey(User)
#рейтинг записи
__rate = models.IntegerField(default=0)
#заголовок записи
caption = models.CharField(max_length=50)
#содержание записи (wiki-размеченный текст)
content = models.TextField()
#поле определяет, является ли запись черновиком
draft = models.BooleanField(default = True)
#дата создания
created = models.DateTimeField(auto_now_add=True)
#дата публикации (устанавливается после снятия опции черновик)
posted = models.DateTimeField()
def inc_rate(self, delta):
self.__rate += delta
def __unicode__(self):
str = '';
if self.draft:
str = ' (draft)';
return self.caption + str
class Admin:
pass
И последние две модели — комментарий к записи в блоге и тэг к записи:
class Tag(models.Model):
""" Тэг (метка) для записи в блоге """
post = models.ForeignKey(Post)
tag = models.CharField(max_length=30)
def __unicode__(self):
return self.tag
class Admin:
pass
class Comment(models.Model):
post = models.ForeignKey(Post)
parent = models.ForeignKey('self')
user = models.ForeignKey(User)
__rate = models.IntegerField()
content = models.TextField()
created = models.DateTimeField(auto_now_add=True)
def inc_rate(self, delta):
self.__rate += delta
def __unicode__(self):
return self.content
class Admin:
pass
Создание структуры базы данных
Пришло время магии :) создадим структуру базы данных из наших моделей. Для этого достаточно ввести команду:
python manage.py syncdb
Сгенерированный SQL-код можно посмотреть при помощи команды:
python manage.py sql default
Манипуляции с моделями
После создания структуры базы данных, можно познакомиться с
Database API предоставляемый джанговским ORM.
Откроем Python консоль и поэкспериментируем с методами моделей:
#> python manage.py shell
#импортируем стандартную модель пользователя
>>>from django.contrib.auth.models import User
#создадим экземпляр класса User и установим ему пароль '12345'
>>> user = User(username = 'testuser', first_name='Василий', last_name='Пупкин')
>>> user.set_password('12345')
#сохраним пользователя
>>> user.save()
#пользователь был успешно добавлен в БД, посмотрим сгенерированный id
>>> user.id
3L
#импортируем все наши модели
>>> from coblog.default.models import *
#создадим профиль пользователя для testuser и сохраним его в БД
>>> profile = Profile(user=user)
>>> profile.save()
#посмотрим карму
>>> user.get_profile().get_karma()
0L
>>> выведем имена всех пользователей
>>> for usr in User.objects.all() :
... print usr
root
testuser
#напишем пост
>>> blog = Blog(caption='Блог о Django')
>>> blog.save()
>>> post = Post(poster= User.objects.get(username='testuser'),
caption='Database API', blog=blog)
>>> post.content = 'вот мы вкратце и ознакомились с Django Database API.'
>>> post.save()
