вторник, 12 мая 2009 г.

Новое в транке Django 1.1

В Django 1.1 Beta 1 попало достаточно интересных вещей, одна из них — это действия над группой элементов в django.contrib.admin рассмотренная в прошлой записи.
Сейчас я хотел бы рассмотреть другие интересные изменения:


  • Новые методы QuerySetdefer, only
  • Редактируемые поля в списке объектов django.contrib.admin
  • "Неуправляемые" модели
  • Прокси модели

defer и only

По умолчанию ORM в Django загружает из базы данных при запросе, все поля объекта. В случае когда преобразование записи базы данных в объект Python занимает долгое время, или полей очень много, или какое-либо из полей содержит большое количество данных — это невыгодно.
Теперь мы можем сказать ORM выбирать только определенные поля из таблицы, с рассчетом на то, что другие не будут использованы.
Приведу пример, допустим у нас есть модель Book
from django.db import models
from django.contrib.auth.models import User

class Book(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=255, db_index=True)
content = models.TextField()
def __unicode__(self): return self.title

В поле title — хранится название книги, а в content — текст книги целиком. Если нам необходимо вывести весь список книг, мы сделаем запрос:
books = Book.objects.all()
На что джанго ответит таким запросом в БД:
SELECT "testapp_book"."id", "testapp_book"."author_id", "testapp_book"."title", "testapp_book"."content" FROM "testapp_book" LIMIT 21
Как видим, content — в списке выбираемых полей. Для нас это критично производительностью. А теперь поступим по другому и используем defer:
books = Book.objects.all().defer('content')
И увидим следующий запрос:
SELECT "testapp_book"."id", "testapp_book"."author_id", "testapp_book"."title" FROM "testapp_book" LIMIT 21
Ну вот, жизнь налаживается. Если теперь мы обратимся к полю content экземпляра модели Book:
print books[0].content
То джанго спросит у БД следующее:
SELECT "testapp_book"."content" FROM "testapp_book" WHERE "testapp_book"."id" = 1
Как видим, defer — это отложенная загрузка полей. Чтобы отключить ее для объекта QuerySet достаточно вызвать метод defer с аргументом None. Чтобы отложить загрузку нескольких полей, достаточно перечислить их как аргументы для defer:
Book.objects.defer('author_id', 'content')
Теперь об only. Only — это метод QuerySet, который работает похожим образом с defer, только наоборот. С помощью only мы можем перечислить поля которые нам необходимо получить, а все остальные выбраны из базы не будут. Например если нам необходим только title книги и логин ее создателя, то запрос к ORM будет следующим:
books = Book.objects.select_related().only('title', 'author__username')

Редактируемые поля в админке

Следующее новшество — это возможность редактирования полей объекта, на странице списка всех объектов. Вот как это выглядит:



Вот как это включается в ModelAdmin:
class BookAdmin(admin.ModelAdmin):
def author_name(obj):
return '%s' % obj.author.username
author_name.short_description = 'Author username'
list_display = ['id', 'title', author_name]
list_editable = ['title']
Ключевая строка:
list_editable = ['title']
Собственно она и говорит о том какие поля будут редактируемыми. Есть небольшой нюанс. По умолчанию первое выводимое поле в таблицы — есть ссылка на объект. Поэтому если мы делаем первое поле редактируемым, мы обязательно должны указать в display_links — какие поля будут ссылками, иначе Django скажет нам что-то вроде этого:
'BookAdmin.list_editable[0]' refers to 'title' which is not defined in 'list_display'.

Неуправляемые модели

В Meta-опциях модели, появилась новая опция managed, по-умолчанию равная True. Эта опция включает или исключает модель из поля зрения syncdb. Это полезно, когда у нас уже есть таблица в базе данных, и мы просто создаем для нее модель. В таком случае syncdb при запуске, не будет трогать существующую таблицу, и пытаться создать новую для модели.

Прокси модели

Прокси модели — это модели, которые не имеют реального отображения в базе данных. Они имеют одну и ту же таблицу в БД, как и проксируемая модель. Для чего это нужно? Допустим нам необходимо, чтобы модель User имела ordering по-умолчанию по емэйлу автора, и некоторые дополнительные функции. Вот так будет выглядеть наша прокси модель:
from django.db import models
from django.contrib.auth.models import User

class MyUser(User):

def say(self, message):
print '%s say %s' % (self.username, message)
class Meta:
proxy = True
ordering = ['email']
И вот так мы ее можем использовать:
>>> u = MyUser.objects.get(username='n0uk')
>>> u.say('hello')
n0uk say hello

Интересно? Читаем документацию:

Комментариев нет:

Отправить комментарий