Download - Web осень 2013 лекция 6
![Page 1: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/1.jpg)
Работа с базой. Django ORM
Александр Бекбулатов
![Page 2: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/2.jpg)
На клиенте
• Cookie (до 4Кб)
• HTML5 Web Storage (до 5Мб)
• В памяти
• На диске
• На диске и в памяти
Где хранить данные
2
На сервере
![Page 3: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/3.jpg)
1. Представление о СУБД
2. Проектирование баз данных
3. Основные операции SQL
4. Работа с базами данных в python
5. Работа с базами данных в django
Работа с базой
3
![Page 4: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/4.jpg)
База данных
взаимосвязанная информация (данные) об
объектах, которая организованна специальным
образом и хранится на каком-либо носителе.
совокупность программных и лингвистических
средств общего или специального назначения,
обеспечивающих управление созданием и
использованием баз данных.
Представление о СУБД
4
СУБД
![Page 5: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/5.jpg)
Функции СУБД
управление данными на дисках и в оперативной памяти
журнализация изменений, резервное копирование и
восстановление базы данных после сбоев;
поддержка языков БД (язык определения данных, язык
манипулирования данными).
Представление о СУБД
5
![Page 6: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/6.jpg)
Таблица – отношение, relation
Строка – кортеж, tuple
Столбец – атрибут, column
Реляционная модель данных
6
Car
Key Model Color Year
1 Toyota Camry 1 2010
2 Audi A4 2 2013
3 Honda Civic 2 2013
Color
Key Name
1 Black
2 Pink
![Page 7: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/7.jpg)
Реляционная модель данных
7
Cousine
Key Name Type
1 Baked fish Main Course
2 Pork Chops Main Course
CousineIngredient
CousineKey IngredientKey
1 3
2 1
Ingredient
Key Name
1 Pork
2 Lamb
3 Salmon
![Page 8: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/8.jpg)
Задачи проектирования
Обеспечение хранения в БД всей необходимой информации.
Обеспечение возможности получения данных по всем
необходимым запросам.
Сокращение избыточности и дублирования данных.
Обеспечение целостности данных (правильности их
содержания): исключение противоречий в содержании данных,
исключение их потери и т.д.
Реляционная модель данных
8
![Page 9: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/9.jpg)
Проектирование на практике
Логическое разделение сущностей
Выделение синтетических первичных ключей
Связи 1:N, N:1 реализуются через внешний ключ
Связи N:M реализуются через промежуточную таблицу
Атрибут с фиксированным числом значений – внешняя
таблица либо поле типа enum
Реляционная модель данных
9
![Page 10: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/10.jpg)
Основные операции SQL
10
![Page 11: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/11.jpg)
SELECT * FROM users WHERE age > 10;
SELECT * FROM users WHERE name = 'masha';
SELECT max(age) FROM users;
SELECT id, name, length(name) AS len
FROM users
WHERE email LIKE '%@mail.ru' AND age > 10
ORDER BY name DESC
LIMIT 10 OFFSET 15
SELECT
11
![Page 12: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/12.jpg)
Агрегатные функции:
COUNT, SUM, AVG, GROUP_CONCAT
SELECT name, count(id) cnt
FROM users
GROUP BY name
ORDER BY cnt
HAVING cnt > 1
SELECT. Агрегация
12
![Page 13: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/13.jpg)
SELECT h.name, a.name
FROM heroes h, abilities a
WHERE h.id = a.hero_id
SELECT h.name, a.name
FROM heroes h
INNER JOIN abilities a ON h.id = a.hero_id
SELECT h.name, a.name
FROM heroes h
LEFT JOIN abilities a ON h.id = a.hero_id
SELECT. JOIN
13
![Page 14: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/14.jpg)
SELECT title
FROM article t1
JOIN (
SELECT rubric_id, MAX(id) max_id
FROM article
GROUP BY rubric_id LIMIT 5
) t2
ON t1.id = t2.max_id;
SELECT. Вложенные запросы
14
![Page 15: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/15.jpg)
INSERT INTO users (name, age) VALUES ('Petr', 10);
UPDATE users SET age = 20 WHERE name = 'Petr';
UPDATE users SET rating = rating + 1;
DELETE FROM users WHERE name = 'Masha';
DELETE FROM users WHERE age > 150;
INSERT, UPDATE, DELETE
15
![Page 16: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/16.jpg)
Проектирование на практике
Создавать индексы для полей, по которым происходит JOIN
Создавать индексы для полей, по которым фильтруются записи (WHERE)
Создавать индексы для полей, по которым идет сортировка (ORDER)
Проверять план выполнения запроса (EXPLAIN)
Управление оптимизатором (принудительное использование индекса, порядок соединения таблиц)
Индексы
16
![Page 17: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/17.jpg)
Работа с базами данных в
python
17
![Page 18: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/18.jpg)
import MySQLdb
db = MySQLdb.connect(
host="localhost", user="joebob",
passwd="moonpie", db="thangs")
cursor = db.cursor()
MySQLdb
18
![Page 19: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/19.jpg)
cursor.execute('update users set age = age + 1
where name = %s', (name,))
cursor.execute('select * from users')
users = cursor.fetchall()
cursor.execute('select * from users where name =
%s', (name,))
user = cursor.fetchone()
MySQLdb
19
![Page 20: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/20.jpg)
cursor.executemany(
"INSERT INTO users (name, age) VALUES (%s,
%s)",
[
("Igor", 18 ),
("Petr", 16 ),
("Dasha", 17 )
])
db.close()
MySQLdb
20
![Page 21: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/21.jpg)
Зачем плейсхолдеры?
email = "' OR '1'='1"
cursor.execute("SELECT * FROM users WHERE email =
'%s'" % email)
Документация
http://mysql-python.sourceforge.net/MySQLdb.html
MySQLdb
21
![Page 22: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/22.jpg)
Работа с базами данных в
django
22
![Page 23: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/23.jpg)
class Employee(object):
def __init__(self, name, salary):
self.name = name
self.salary = salary
def __unicode__(self):
return unicode(self.name)
def get_info(self):
return "Name : %s, Salary: %s" % (self.name,
self.salary)
class Programmer(Employee):
def __init__(self, name, salary, lang):
super(Programmer, self).__init__(name,
salary)
self.lang = lang
Классы в Python
23
![Page 24: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/24.jpg)
>>> e1 = Programmer(u'Vasya', 100, 'VB')
>>> print u'Welcome %s' % e1
Welcome Vasya
>>> e1.get_info()
u'Name : Vasya, Salary: 100'
>>> e1.lang
'VB'
Классы в Python
24
![Page 25: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/25.jpg)
cursor.execute('select * from users where age >
18')
for user in cursor.fetchall():
pk, name, age = user
print name
VS
for user in User.objects.filter(age__gt=18):
print user.name
Raw SQL vs ORM
25
![Page 26: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/26.jpg)
class Post(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
creation_date =
models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return '/post/%d/' % self.pk
def get_next_post(self):
"""Return the next entry"""
class Meta:
ordering = ['-creation_date’]
Модели и типы данных
26
![Page 27: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/27.jpg)
Модели и типы данных
27
Типы данных Mysql Типы полей Django
varchar(N) CharField
EmailField
SlugField
ImageField
longtext TextField
tinyint(1) BooleanField
int(11) IntegerField
smallint(5) unsigned PositiveSmallIntegerField
date DateField
datetime DateTimeField
![Page 28: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/28.jpg)
Свойства полей моделей
null, blank, choices, db_index, default, editable,
help_text, max_length, primary_key, unique, unique_for_date,
unique_for_month, unique_for_year, verbose_name
https://docs.djangoproject.com/en/dev/ref/models/fields/
Модели и типы данных
28
![Page 29: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/29.jpg)
class Post(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
creation_date =
models.DateTimeField(default=datetime.datetime.now)
category = models.ForeignKey(Category,
on_delete=models.SET_NULL)
tags = models.ManyToManyField(Tag)
Связи между таблицами
29
![Page 30: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/30.jpg)
ForeignKey, OneToOneField
ForeignKey = IntegerField + Constraint
OneToOneField = ForeignKey + unique
post.category – связанный объект (отдельный запрос к
связанной сущности)post.category_id – значение атрибута модели (просто id)
В обратную сторону:
category.post_set.all()
Связи между таблицами
30
![Page 31: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/31.jpg)
ForeignKey, OneToOneField
Изменение/удаление внешнего ключа
• RESTRICT -> models.PROTECT
• CASCADE -> models.CASCADE
• SET NULL -> models.SET_NULL
• NO ACTION -> models.DO_NOTHING
Связи между таблицами
31
![Page 32: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/32.jpg)
Связи между таблицами
32
Post
id
title
content
creation_date
category
Tagidtitledescription
PostTag
post_idtag_id
ManyToManyField
![Page 33: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/33.jpg)
ManyToManyField
post.tags – related managerpost.tags.all()
В обратную сторону:tag.post_set.all()
Связи между таблицами
33
![Page 34: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/34.jpg)
python manage.py shell
>>> from blog.models import Category, Post
>>> from django.db import connection
>>> # Вставка и замена
>>> c = Category(title="Python")
>>> c.save()
>>> c.id
1
>>> c.title="About Python"
>>> c.save()
ORM API
34
![Page 35: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/35.jpg)
python manage.py shell
>>> print '\n'.join(q['sql'] for q in
connection.queries)
INSERT INTO `blog_category` (`title`,
`description`) VALUES ('Python', '')
SELECT (1) AS `a` FROM `blog_category` WHERE
`blog_category`.`id` = 1 LIMIT 1
UPDATE `blog_category` SET `title` = 'About
Python', `description` = '' WHERE
`blog_category`.`id` = 1
ORM API
35
![Page 36: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/36.jpg)
>>> # Выборка
>>> Category.objects.all()
[<Category: About Python>]
>>> print Category.objects.all().query
SELECT `blog_category`.`id`,
`blog_category`.`title`,
`blog_category`.`description` FROM `blog_category`
>>> Category.objects.filter(id=1)
[<Category: About Python>]
>>> c = Category.objects.get(id=1)
>>> c
<Category: About Python>
>>> c.post_set.all()
[]
ORM API
36
![Page 37: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/37.jpg)
>>> c.post_set.create(title="New post",
content="Many words")
<Post: New post>
>>> c.post_set.count()
1
>>> p = Post.objects.get(title="New post")
>>> p.category
<Category: About Python>
>>> p.category_id
1
>>> Post.objects.filter(category__title="About
Python")
<Post: New post>
>>> c.delete()
ORM API
37
![Page 38: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/38.jpg)
Debug Toolbarhttps://github.com/django-debug-
toolbar/django-debug-toolbar
38
![Page 39: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/39.jpg)
Методы Manager
slice [10:20]
.all(), .filter(), .exclude(), .order_by()
.values(), .values_list()
.get(), .get_or_create(), .count(), .exists()
.select_related(), .prefetch_related()
.update(), .delete()
Manager и RelatedManager
39
![Page 40: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/40.jpg)
Методы RelatedManager
.create(**kwargs)
.add(obj1[, obj2, ...])
.remove(obj1[, obj2, ...])
.clear()
Manager и RelatedManager
40
![Page 41: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/41.jpg)
Queryset ленивый
qs = Category.objects.all()
if not user.is_admin:
qs = qs.filter(active=True)
print qs.count()
Особенности QuerySet
41
![Page 42: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/42.jpg)
Избегайте лишних запросов в базу
Foreign key кешируется
post.category
Queryset – нет.
Если нужно использовать несколько раз – кешируйте явно
question_list = list(Question.objects.all())
Особенности QuerySet
42
![Page 43: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/43.jpg)
Атомарное обновление
Question.objects.filter(pk=10) \
.update(rating=models.F('rating') + 1)
https://docs.djangoproject.com/en/dev/ref/models/querysets/
Особенности QuerySet
43
![Page 44: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/44.jpg)
CREATE DATABASE ask_db CHARACTER SET utf8
COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON ask_db.* TO
ask_user@localhost identified BY 'secret';
Создание базы
44
![Page 45: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/45.jpg)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'ask_db',
'USER': 'ask_user',
'PASSWORD': 'secret',
'HOST': '',
'PORT': '',
}
}
Подключение базы
45
![Page 46: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/46.jpg)
Проверка моделей
python manage.py validate
Вывод SQL
python manage.py sqlall <app_name>
Выполнение SQL в базе
python manage.py syncdb
Полезные команды
46
![Page 47: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/47.jpg)
CREATE TABLE `blog_post` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`title` varchar(255) NOT NULL,
`content` longtext NOT NULL,
`creation_date` datetime NOT NULL,
`category_id` integer NOT NULL
)
;
ALTER TABLE `blog_post` ADD CONSTRAINT
`category_id_refs_id_e0428883` FOREIGN KEY
(`category_id`) REFERENCES `blog_category` (`id`);
ALTER TABLE `blog_post_tags` ADD CONSTRAINT
`post_id_refs_id_c9e37cca` FOREIGN KEY (`post_id`)
REFERENCES `blog_post` (`id`);
CREATE INDEX `blog_post_42dc49bc` ON `blog_post`
(`category_id`);
SQL. Создание таблиц
47
![Page 48: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/48.jpg)
DROP TABLE blog_post;
ALTER TABLE users ADD COLUMN language
enum('ru', 'en') NOT NULL DEFAULT 'ru' after
name;
ALTER TABLE users DROP COLUMN langauge;
ALTER TABLE users ADD INDEX ('name');
ALTER TABLE users CHANGE nickname fullname
varchar(255) NOT NULL;
SQL. Удаление и изменение таблиц
48
![Page 49: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/49.jpg)
1. DROP DATABASE, CREATE DATABASE
2. DROP TABLE, CREATE TABLE
3. ALTER TABLE
4. South
Миграции
49
![Page 50: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/50.jpg)
• Автоматическое создание миграций
• Поддержка различных СУБД
• Прямые и обратные миграции
South
50
![Page 51: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/51.jpg)
1. Создать миграцию
./manage.py schemamigration ask --initial
2. Применить миграцию
./manage.py migrate ask
3. Изменить модель
4. Создать миграцию
./manage.py schemamigration ask --auto
5. Применить миграцию
./manage.py migrate ask
South Workflow
51
![Page 52: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/52.jpg)
1. MySQL http://dev.mysql.com/doc/refman/5.5/en/index.html
2. Mysqldb http://mysql-python.sourceforge.net/MySQLdb.html
3. Django http://docs.djangoproject.com/en/dev/
4. Django Debug Toolbar https://github.com/django-debug-toolbar/django-debug-toolbar
52
![Page 53: Web осень 2013 лекция 6](https://reader034.vdocuments.pub/reader034/viewer/2022050922/559b88b81a28ab72158b461d/html5/thumbnails/53.jpg)
1. Установить Django Debug Toolbar
2. Установить MySQL, python-mysqldb. Создать базу данных и пользователя для работы с базой
3. Описать модели для проекта «Вопросы и ответы»
4. Наполнить базу тестовыми данными
53