Июнь 3, 2008 в 00:43 |
db
django
python
snippets
web
- Автор Александр Кошелев |
|
Я всё продолжаю по рабочим и не только нуждам ковырять наследование моделей, поэтому как и обещал - то ли ещё есть!
Очередной сюрприз ждал меня, когда я обновляя свой блог-движок под текущий транк. Я обнаружил сломанным блок "Архив" из-за того, что метод dates() перестал возвращать уникальные значения на месяца, а выдавал мне всё подряд. Я сильно удивился. Но пофиксил всё при помощи, в последнее время моего любимого, set. Да, костыль, но ковырять дальше пока желания нет.
Далее уже по рабочим нуждам обновления тест наборы для приложения, проявились некоторые особенности работы fixtures. Для примера, допустим у нас есть такие связанные наследованием модели:
class Base( models.Model ):
field1 = models.IntegerField( default = 10 )
# + неявное поле id
class Derived( Base ):
field2 = models.IntegerField( default = 1 )
# + неявное поле base_ptr
Сериализатор дампит модель наследника целиком, т.е. со всеми полями в том числе и родителей.
При загрузке модели родителей не могут подцепить свой первичный ключ, а просто делают новый INSERT, получая тем самым новый id. Потом этот ...
Май 19, 2008 в 16:11 |
django
orm
python
snippets
web
- Автор Александр Кошелев |
|
И так, некоторые время назад состоялось моё погружение в новый для джанго мир наследования моделей. Как и в моих домашних проектах и так и в рабочих. Исследованию подверглось мульти-табличное наследование. Среди достаточного количества удобных и полезных свойств наследования преподнесло несколько неожиданностей и даже ошибок, которые были обнаружены в механизме самой джанги.
Начнем с особенностей:
Кастомные менеджеры наследуются. Что вполне логично, если учесть, что менеджер это всего-лишь обычное поле класса, которое при наследовании переходит к наследнику. Но, что не очень очевидно на первый взгляд, так то, что он остается "прикрепленным" к модели предка и его использование с моделью наследника будет давать не совсем ожидаемы результат. Вот пример:
class Base( models.Model ):
field1 = models.IntegerField()
objects = models.Manager()
my_custom_manager = MyManager()
class Derived( Base ):
field2 = models.IntegerField()
#...
Derived.my_custom_manager.filter( field2 = 777 )# Вот это не сработает
# и ругнется на отсутсвие данного поля у Base модели, что есть правда
Отсюда вывод - переопределяйте свои менеджеры в моделях наследниках. Вот соответствующее обсуждение в джанго-девелоперс
Теперь немного ...
Май 12, 2008 в 00:54 |
django
python
snippets
web
- Автор Александр Кошелев |
|
Давно уже сталкиваюсь с одним неудобством в повседневной работе с джангой.
Например у нас есть моделька:
class Entry( models.Model ):
title = models.CharField( max_length = 150 )
type = <...>
И каким полем выразить тип (да, знаю, что имя конфликтует со встроенным, но тут это не принципиально)? "Ха!" - скажут некоторые. Да просто взять IntegerField и сделать типы целыми числами от 0 до сколько надо. Легко!
TYPES = ( ( 0, _( "inactive" ) ),
( 1, _( "active" ) ) )
class Entry( models.Model ):
title = models.CharField( max_length = 150 )
type = models.PositiveIntegerField( choices = TYPES )
Казалось бы, проблема решена. И этим можно пользоваться. Но, тут сразу начинаются неудобства.
Для того чтобы код не превращался в склад "магических чисел" надо добавить соответствующие константы, которые описывают эти два типа.
INACTIVE = 0
ACTIVE = 1
# или даже
INACTIVE, ACTIVE = range( 0, 2 )
потом можно пойти ещё дальше и выразить choices через них, чтобы было меньше дублирования
TYPES = ( ( INACTIVE, _( "inactive" ) ),
( ACTIVE, _( "active" ) ) )
Теперь можно вполне себе удобно использовать это хозяйство. И выборки делать и прочие проверки ...
Февраль 5, 2008 в 02:07 |
django
python
snippets
web
- Автор Александр Кошелев |
|
А вы задумывались как работает волшебный manage.py? Как он там внутри устроен? А, между прочим, очень интересно.
Вначале чуть-чуть истории. До августа прошлого года вся логика manage.py была в одном большом файле django/core/management.py. Там обработчики всех команд были написаны скопом, от чего файл стал просто монcтруозным и трудно поддавался созерцанию. Да и не расширяем извне.
Видимо, разработчикам джанги это надоело и они в целях облегчения своей жизни и жизни всех сочувствующих изменили систему. Её основным преимуществом является то, что новая система позволяет расширять набор команд в сторонних приложениях.
Вся машинерия переехала в django/core/management/commands/. Каждая команда расположена в отдельном файле. Имя файла является именем команды и именно его нужно указывать первым параметром в manage.py.В этом файле должен быть объявлен класс Command в общем случае наследник от BaseCommand. В недрах которых скрывается логика обработки параметров командной строки ОС посредством стандартного модуля optparse.
Основным аспектом создания команды является реализация метода handle, который принимает ...
Январь 29, 2008 в 22:54 |
db
django
python
snippets
web
шаблоны
- Автор Александр Кошелев |
|
Часто нужно в шаблоне вывести какой-то конфигурационный параметр. Нет, не тот который в settings.py, а тот который хранится в базе. Ну например префикс заголовка страниц, содержимое мета-тега в head или ещё какую-то информацию. Эти все данные(пары имя-значение) можно либо хранить в простой модели или взять что-то стороннее посерьезней, например dbsettings.
Для примера я возьму простую модель:
class Entry( models.Model ):
name = models.CharField( max_length = 50, unique = True )
value = models.CharField( max_length = 150 )
Здесь и далее буду писать упрощенный код
Всё, данные есть где хранить, но их ещё и нужно удобно вывести в шаблон. Первое что приходит в голову для решения - сделать шаблонный тег. Да, и вправду просто и сердито:
@register.simple_tag
def get_conf( name ):
return Entry.objects.get( name = name )
И использовать легко, примерно так:
<meta name="keywords" content="{% get_conf "meta_keywords" %}"/>
Но у этого способа по сути одно маленькое положительное качество - в этот тег можно передать переменную, а не жестко закодированную строку("hardcoded" - правильно перевел?:)) с названием. Но ...