Лекция 6: Работа с данными. Django ORM
-
Upload
technosphere1 -
Category
Software
-
view
744 -
download
1
description
Transcript of Лекция 6: Работа с данными. Django ORM
Работа с базой.
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