Лекция 6: Работа с данными. Django ORM

50
Работа с базой. Django ORM Сергей Лихобабин Техносфера . 2014

description

Лекция 6: Работа с данными. Django ORM

Transcript of Лекция 6: Работа с данными. Django ORM

Page 1: Лекция 6: Работа с данными. Django ORM

Работа с базой.

Django ORM

Сергей Лихобабин

Техносфера. 2014

Page 2: Лекция 6: Работа с данными. Django ORM

Где хранить данныеНа клиенте

Cookie (4кб)

Web Storage

На сервере

В памяти

На диске

На диске и в памяти

Page 3: Лекция 6: Работа с данными. Django ORM

Работа с базойПредставление о СУБД

Проектирование БД

Основные операции SQL

Работа с БД в Python

Работа с БД в Django

Page 4: Лекция 6: Работа с данными. Django ORM

БДВзаимосвязанные даные специальным образом

хранящиеся на каком-либо носителе

СУБДПрограммный комплекс обеспечивающий работу с

данными в БД

Page 5: Лекция 6: Работа с данными. Django ORM

Функции СУБДУправление данными на дисках и воперативной памяти

Журнализация, резервное копирование

Page 6: Лекция 6: Работа с данными. Django ORM

Реляционная модельданных

Таблица - отношение, relation

Строка - кортеж, tuple

Столбец - атрибут, column

Page 7: Лекция 6: Работа с данными. Django ORM

Реляционная модельданных

Page 8: Лекция 6: Работа с данными. Django ORM

Реляционная модельданных

Page 9: Лекция 6: Работа с данными. Django ORM

Задачи проектированияОбеспечение хранения всей необходимойинформации

Обеспечение возможности получения данныхпо всем запросам

Сокращение избыточности и дублированияданных

Обеспечение целостности данных

Page 10: Лекция 6: Работа с данными. Django ORM

Проектирование напрактике

Логическое разделение сущностей

Выделение первичных ключей

Связи 1:N реализуются через внешний ключ

Связи N:M реализуются через промежуточнуютаблицу

Аттрибут с фиксированным числом значений -внешняя таблица либо enum

Page 11: Лекция 6: Работа с данными. Django ORM

Основные операции SQL

Page 12: Лекция 6: Работа с данными. Django ORM

SELECT SELECT * FROM users WHERE age > 10;SELECT * FROM users WHERE name = 'masha';SELECT MAX(age) FROM users;

SELECT id, name, LENGTH(name) AS lenFROM usersWHERE email LIKE '%@mail.ru' AND age > 10ORDER BY name DESCLIMIT 10 OFFSET 15;

Page 13: Лекция 6: Работа с данными. Django ORM

Агрегатные функцииCOUNT, SUM, AVG, GROUP

SELECT name, count(id) cntFROM usersGROUP BY nameORDER BY cntHAVING cnt > 1

Page 14: Лекция 6: Работа с данными. Django ORM

Join SELECT h.name, a.nameFROM heroes h, abilities aWHERE h.id = a.hero_id;

SELECT h.name, a.nameFROM heroes hINNER JOIN abilities a ON h.id = a.hero_id;

SELECT h.name, a.nameFROM heroes hLEFT JOIN abilities a ON h.id = a.hero_id;

Page 15: Лекция 6: Работа с данными. Django ORM

Вложенные запросы SELECT title FROM article t1 JOIN ( SELECT rubric_id, MAX(id) max_id FROM article GROUP BY rubric_id LIMIT 5) t2 t1.id = t2.max_id;

Page 16: Лекция 6: Работа с данными. Django ORM

INSERT, UPDATE, DELETE 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;

Page 17: Лекция 6: Работа с данными. Django ORM

Индексы

Page 18: Лекция 6: Работа с данными. Django ORM

Индексы на практикеИндексы для полей, по которым происходитJOIN

Индексы для полей, по которым фильтруютсязаписи

Индексы для полей, по которым идетсортировка

Проверять план выполнения запроса EXPLAIN

Управление оптимизатором запросов

Page 19: Лекция 6: Работа с данными. Django ORM

Работа с БД в python

Page 20: Лекция 6: Работа с данными. Django ORM

MySQLdb import MySQLdb

db = MySQLdb.connect( host="localhost", user="bob", passwd="secret", db="goodies"

cursor = db.cursor()

Page 21: Лекция 6: Работа с данными. Django ORM

MySQLdb 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()

Page 22: Лекция 6: Работа с данными. Django ORM

MySQLdb cursor.executemany( "INSERT INTO users (name, age) VALUES (%s, %s)", [ ("Igor", 18 ), ("Petr", 16 ), ("Dasha", 17 ) ]

db.close()

Page 23: Лекция 6: Работа с данными. Django ORM

Плейсхолдеры email = "' OR '1'='1"cursor.execute( "SELECT * FROM users WHERE email = '%s'" % email

Page 24: Лекция 6: Работа с данными. Django ORM

Работа с БД в django

Page 25: Лекция 6: Работа с данными. Django ORM

Классы в python class Employee(object): def __init__(self, name, salary): self.name = name self.salary = salary

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

Page 26: Лекция 6: Работа с данными. Django ORM

Классы в python >>> e1 = Programmer(u'Vasya', 100, 'VB')>>> print u'Welcome %s' % e1Welcome Vasya>>> e1.get_info()u'Name : Vasya, Salary: 100'>>> e1.lang'VB'

Page 27: Лекция 6: Работа с данными. Django ORM

Raw SQL vs ORM 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

Page 28: Лекция 6: Работа с данными. Django ORM

Модели и типы данных 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

class Meta: ordering = ['-creation_date’]

Page 29: Лекция 6: Работа с данными. Django ORM

Модели и типы данных

Page 30: Лекция 6: Работа с данными. Django ORM

Связи между таблицами 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)

Page 31: Лекция 6: Работа с данными. Django ORM

ForeignKey, OneToOneForeignKey = IntegerField + Constraint

OneToOneField = ForeignKey + unique

post.category VS post.category_id

Обратная связь - category.post_set

Page 32: Лекция 6: Работа с данными. Django ORM

ForeignKey, OneToOneРеакция на удаление внешнего ключа

RESTRICT -> models.PROTECT

CASCADE -> models.CASCADE

SET NULL -> models.SET_NULL

NO ACTION -> models.DO_NOTHING

Page 33: Лекция 6: Работа с данными. Django ORM

ManyToManyFieldpost.tags - related manager

Обратная связь - tag.post_set

Page 34: Лекция 6: Работа с данными. Django ORM

ORM API python manage.py shell>>> from blog.models import Category, Post>>> from django.db import connection>>> # Вставка и замена>>> c = Category(title="Python")>>> c.save() >>> c.id

>>> c.title="About Python">>> c.save()

Page 35: Лекция 6: Работа с данными. Django ORM

ORM API >>> 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

Page 36: Лекция 6: Работа с данными. Django ORM

ORM API >>> Category.objects.all() [<Category: About Python>]>>> print Category.objects.all().querySELECT 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()

Page 37: Лекция 6: Работа с данными. Django ORM

ORM API >>> c.post_set.create(title="New post", content="Many words")<Post: New post>>>> c.post_set.count()

>>> p = Post.objects.get(title="New post")>>> p.category<Category: About Python>>>> p.category_id

>>> Post.objects.filter(category__title="About Python")<Post: New post>>>> c.delete()

Page 38: Лекция 6: Работа с данными. Django ORM

Debug Toolbarhttps://github.com/django-debug-

toolbar/django-debug-toolbar

Page 39: Лекция 6: Работа с данными. Django ORM

Managerslice [10:20]

.all(), .filter(), exclude(), .order_by()

.values(), .values_list()

.get(), .get_or_create(), .count(), .exists()

.select_related(), prefetch_related()

.update(), .delete()

Page 40: Лекция 6: Работа с данными. Django ORM

RelatedManager.create(**kwargs)

.add(obj1[, obj2, ...])

.remove(obj1[, obj2, ...])

.clear()

Page 41: Лекция 6: Работа с данными. Django ORM

Ленивое выполнениеQuerySet

qs = Category.objects.all() not user.is_admin:

qs = qs.filter(active=True)print qs.count()

Page 42: Лекция 6: Работа с данными. Django ORM

Избегайте лишнихзапросов в базу

Foreign key кэшируется post.category

Queryset - нет question_list = list(Question.objects.all())

Page 43: Лекция 6: Работа с данными. Django ORM

Атомарное обновлениеQuerySet

Question.objects.filter(pk=10) \.update(rating=models.F('rating') + 1)

Page 44: Лекция 6: Работа с данными. Django ORM

Полезные командыПроверка моделей

python manage.py validate

Вывод SQL python manage.py sqlall <app_name> </app_name>

Выполнение SQL в базе python manage.py syncdb

Page 45: Лекция 6: Работа с данными. Django ORM

МиграцииDROP DATABASE, CREATE DATABASE

DROP TABLE, CREATE TABLE

ALTER TABLE

South

Page 46: Лекция 6: Работа с данными. Django ORM

SouthАвтоматическое создание миграций

Поддержка различных СУБД

Прямые и обратные миграции

Page 47: Лекция 6: Работа с данными. Django ORM

Инициализация South1. Создать миграцию

2. Применить миграцию

./manage.py schemamigration ask --initial

./manage.py migrate ask

Page 48: Лекция 6: Работа с данными. Django ORM

Миграция с South1. Изменить модель2. Создать миграцию

3. Применить миграцию

./manage.py schemamigration ask --auto

/manage.py migrate ask

Page 49: Лекция 6: Работа с данными. Django ORM

Полезные ссылкиMySQLhttp://dev.mysql.com/doc/refman/5.5/en/index.html

Mysqldb http://mysql-python.sourceforge.net/MySQLdb.html

Django http://docs.djangoproject.com/en/dev/

Django Debug Toolbar https://github.com/django-debug-toolbar/django-debug-toolbar

Page 50: Лекция 6: Работа с данными. Django ORM

Спасибо за внимание

Сергей Лихобабин

[email protected]