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

Preview:

DESCRIPTION

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

Citation preview

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

Django ORM

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

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

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

Cookie (4кб)

Web Storage

На сервере

В памяти

На диске

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

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

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

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

Работа с БД в Python

Работа с БД в Django

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

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

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

данными в БД

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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;

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

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

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;

Вложенные запросы 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;

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;

Индексы

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

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

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

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

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

Работа с БД в python

MySQLdb import MySQLdb

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

cursor = db.cursor()

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

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

db.close()

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

Работа с БД в django

Классы в 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

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

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

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

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

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

ForeignKey, OneToOneForeignKey = IntegerField + Constraint

OneToOneField = ForeignKey + unique

post.category VS post.category_id

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

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

RESTRICT -> models.PROTECT

CASCADE -> models.CASCADE

SET NULL -> models.SET_NULL

NO ACTION -> models.DO_NOTHING

ManyToManyFieldpost.tags - related manager

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

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

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

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

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

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

toolbar/django-debug-toolbar

Managerslice [10:20]

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

.values(), .values_list()

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

.select_related(), prefetch_related()

.update(), .delete()

RelatedManager.create(**kwargs)

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

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

.clear()

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

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

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

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

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

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

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

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

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

python manage.py validate

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

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

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

DROP TABLE, CREATE TABLE

ALTER TABLE

South

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

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

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

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

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

./manage.py schemamigration ask --initial

./manage.py migrate ask

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

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

./manage.py schemamigration ask --auto

/manage.py migrate ask

Полезные ссылки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

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

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

s.lihobabin@corp.mail.ru

Recommended