Tag django, everything about django : livedev.org
livedev.org [http://livedev.org] Журнал Web2.0 разработчика Django signals по-новому 2 Posted by dobrych Mon, 08 Sep 2008 17:35:00 GMT На пути к 1.0 релизу Django претерпевал немало радикальных изменений. Одно из них рефакторинг системы сигналов. Если вы первый раз читаете и не в курсе «что это такое и с чем его едят», то скажу в двух словах. Это система реагирования на события приложения. Любой JavaScript или прикладной UI программист хорошо знаком с системой событий (event) — клик мышкой, нажатие горячей клавиши и т.п. Для программистов серверной части веба все выглядит немного по другому. Есть HTTP-запрос и есть его обработчик, анализируется как правило URL на предмет «кому отправлять запрос». Но на самом деле это та же система сигналов-событий, только узкопрофилированная под обработку HTTP-запросов. Оказывается серверная часть веб-приложения тоже может, и я уверен, просто должна генерировать намного больший спектр сигналов, чем просто обработку URL и данных запроса. С чем успешно и справляется Django. Теперь немного прозы. Какие же события может ловить Django «из-коробки». pre_init — перед запуском метода-конструктора __init__() модели; post_init — после выполнения метода __init__() модели; pre_save — перед сохранением экземпляра модели в базу; post_save — после успешного сохранения экземпляра модели в базу; pre_delete , post_delete — перед и после удаления экземпляра модели из базы; post_syncdb — генерируется админкой Django после установки нового приложения ( INSTALLED_APPS ); request_started , request_finished , got_request_exception — генерируются при обработке HTTP-запросов; template_rendered — генерируется только в режиме тестирования приложения. Итак сигналы *_init , _*save , *_delete и post_syncdb генерируются системой моделей Django и их можно импортировать из django.db.models.signals . Сигналы обработки HTTP-запросов из django.core.signals . И тестовый template_rendered из django.test.signals . А теперь реальный пример, как повесить обработчик на событие-сигнал сохранения модели. В нашем случае будет требоваться определить тип mime закачанного файла перед его сохранением в базу. Код модели: class MimeType(models.Model): """ Mime Types table """ name = models.CharField(max_length=200) slug = models.SlugField() def __unicode__(self): return self.name class Item(models.Model): """ Main file """ name = models.CharField(max_length=200) slug = models.SlugField() file = models.FileField(upload_to='files', blank=True) mime = models.ForeignKey(MimeType, blank=True, null=True) upload_date = models.DateTimeField(auto_now_add=True) def __unicode__(self): return self.name def set_mime(self, mime): obj, created = MimeType.objects.get_or_create(name=mime, slug=slugify(mime)) self.mime = obj Посмотрите на метод set_mime модели Item . Он создает новый объект MimeType или использует если он уже создан. При этом не сохраняя модель Item . Теперь я пишу функцию-callback, которая будет вызываться по событию сохранения модели Item . import mimetypes import os.path # init mime types dict mimetypes.init() def add_mime_type(instance, **kwargs): """ Adding mime-type to uploaded file (for future use). Would be called on post-save. """ if not hasattr(instance, 'mime') or not hasattr(instance, 'file'): raise Exception("Object %s does not have 'mime' attribute! Can't set mime-type!" % instance) if instance.file: extension = os.path.splitext(instance.file.path)[1].lower() instance.set_mime(mimetypes.types_map[extension]) Итак, функция-callback add_mime_type принимает параметр instance , который является экземпляром модели, сгенерировавшим сигнал (в нашем случае модели Item ). Вторым параметром принимает словарь (dictionary). Кстати, это и есть один из моментов обратной несовместимости. После рефакторинга каждая функция-callback должна принимать параметр **kwargs . Теперь третий самый простой шаг — связывание модели с сигналом. В самом конце файла моделей добавилась строчка: models.signals.pre_save.connect(add_mime_type, sender=Item) Теперь перед каждым сохранением объектов Item, будет выполняться проверка и установка Mime-типа. Кстати, я советую если у вас больше одного сигнала, выносите их в отдельный файл signals.py или можно по-старинке писать в файле моделей (что ИМХО иногда мешает чтению кода). Почитать про сигналы можно еще в официальной доке: Django Signals и Django Built-in signal reference . Почитать про рефаторинг можно на странице Backwards Incompatible Changes и в соответствующем коммите 8223 . Александр Кошелев тоже немного раньше написал по теме, статья « А вы поймали новые сигналы? » с хорошим примером создания абстрактного сигнала. «На сегодня все. Вопросы в студию» :-) Posted in статьи Tags django , python , signals Meta 2 comments , permalink , rss , atom Django 1.0 Posted by dobrych Thu, 04 Sep 2008 08:35:00 GMT Не буду говорить насколько релиз важен или наоборот нет. Я в целом разделаю точку зрения Ивана . Но думаю, что как раз релиз является отличным поводом написать много новых заметок, статей и примеров кода по новым и переделанным фичам. Так что ждите в скором будущем новых статей по Django тематике. Думаю осветить подробно: эффективное создание форм; кастомизация django admin интерфейса; трюки с FileField и аплоадом в общем; сигналы в django. Posted in заметки Tags django , python Meta no comments , permalink , rss , atom Django + Spawning! 3 Posted by dobrych Thu, 31 Jul 2008 12:36:00 GMT Вышла новая переписанная версия Spawning — WSGI сервера. Главное достоинство это non-blocking IO , т.е. большие возможности по масштабируемости (scaling). Spawning is a wsgi server which supports multiple processes, multiple threads, non-blocking HTTP io, and automatic graceful upgrading of code. Это очередной способ запуска django и других python-приложений для веб. Пример команды для запуска django процесса: spawn --factory=spawning.django_factory.config_factory settings --port 9090 -s 4 -t 100 Пример для запуска приложений через paste (например Pylons используют paste для деплоя): spawn --factory=spawning.paste_factory.config_factory development.ini Если захотелось поставить и попробовать: sudo easy_install Spawning Почитайте еще обзор Эрика на английском. Update : как ни странно товарищ Александр aka piranha практически одновременно со мной написал статью как раз про деплой через WSGI. Так что моя заметка «пролетает как фанера над Парижем», ибо мягко говоря Spawing не самый быстрый вариант :-) Читайте — Amazon byteflow: WSGI серверы кратко и юзайте fapws2 . Posted in заметки Tags deploy , django , python , spawn , wsgi Meta 3 comments , permalink , rss , atom Django newforms-admin в trunk 1 Posted by dobrych Sat, 19 Jul 2008 04:01:00 GMT Есть! Наконец-то замержили в trunk django newforms-admin — Changeset 7967 . Учтите, что после апдейта нужно будет переписывать код для работы админки. Но новость однозначно отличная! Много новых фич и ближе к релизу 1.0 Как говорят «там»: stay tuned! Будут примеры по настройке новой админки. А товарищу Brian Rosner респект за удачный мерж. Posted in заметки Tags admin , django , newforms , ui Meta 1 comment , permalink , rss , atom File uploads в django 3 Posted by dobrych Tue, 01 Jul 2008 16:39:00 GMT ДА! Это наконец-то случилось! Иван может петь победоносную песню, он так долго боролся за решение этого вопроса! By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold the entire contents of the upload in memory. This means that saving the file involves only a read from memory and a write to disk and thus is very fast. However, if an uploaded file is too large, Django will write the uploaded file to a temporary file stored in your system’s temporary directory. Полная дока по новому аплоаду — Django | File Uploads | Django Documentation . Posted in заметки Tags code , django , upload Meta 3 comments , permalink , rss , atom Линкотека №3. «Как ляжет карта». 3 Posted by dobrych Thu, 22 May 2008 20:29:00 GMT Как я вчера обещал, начинаю активнее добавлять контент :-) Третий выпуск «Линкотеки» посвящен картографии и Google maps в частности. К слову, тема вообще очень интересная и популярная. Я, честно говоря, недооценивал ее увлекательность и предлагаемые возможности, пока не столкнулся с ней в одном их своих новых проектов. В блогах все чаще можно услышать новомодную фразу гео-тегирование , а на разных социальных сервисах все чаще предлагают привязать какую-то виртуальную информацию к географическим координатам. Так что будте готовы наваять свой код, когда столкнетесь с необходимостью работать с гео-данными. Mapstraction — JavaScript библиотека для работы с многими картографическими сервисами через единый API. Modest Maps — Библиотека для работы с картографическими сервисами на ActionScript (v2 / v3) и Python . cfis — Блог Charlie Savage, разработчика GIS систем. Много информации общего характера для понимания тонкостей картографического софта, плюс примеры кода . Google maps. Snap to Polyline (example) — Пример JavaScript кода для привязки курсора к полигонам и полилиниям в Google maps. Google maps. Resizable Polygons (example) — Пример JavaScript кода для создания полигонов с возможностью ресайзинга в Google maps. Take Control of Your Maps — Отличный обзор картографического (GIS) софта для построения веб-приложений от «A List Apart». jMaps jQuery plugin — Плагин к jQuery для базовой работы с Google maps. GeoDjango — Отдельная ветка django , отлично заточенная на работу с гео-данными (GIS). Фич очень много, советую хотя бы ради интереса ознакомится. Главным я считаю полную интеграция с PostgreSQL PostGIS на уровне ORM. django-geo — В отличии от GeoDjango, облегченный вариант для интеграции гео-данных в ваш django-проект. На этом, пожалуй остановлюсь. Если тема GIS и работы с гео-данными интересна, дайте знать. Если нет, то я не буду закидывать вас неинтересным контентом. Просто есть мысли в следующих постах привести некоторые куски кода по теме с объяснениями. Posted in заметки Tags ActionScript , API , django , example , GIS , google , javascript , maps Meta 3 comments , permalink , rss , atom Подкаст о веб-разработке 36 Posted by dobrych Tue, 25 Mar 2008 22:29:00 GMT Сегодня важное событие у меня. Я наконец-то смог выродить подкаст о веб-разработке, который планировал оч давно записать. Даже не только планировал, но и пробывал. Итак, это моя третья попытка — более-менее удачная. Не могу сказать что я на 100% доволен результатом, но как говориться «первый блин можно и простить» :-) Для меня намного важнее узнать ваше мнение, уважаемые читатели! На сколько вам был бы полезен вообще подкаст о веб-разработке. И о каких темах вы бы хотели услышать выпуски в будующем. Любые ваши комментарии (желательно конструктивные) будут мотивировать меня для дальнейшей записи. А так как я не диктор и не работал никогда на радио, дается мне сие записывание нелегко... Так что хотелось бы знать интересно ли будет что-то подобное для вас. Жду фидбека, а пока качайте 10 минутное mp3 весом в 14Мб :-) Отдельный фид для подкаста скоро будет. Update : сделал еще копию подкаста с битрейтом 128 на 10Мб Posted in podcast Tags development , django , php , podcast , python , rails , ruby , web Meta 36 comments , permalink , rss , atom Две модели в newforms 10 Posted by dobrych Mon, 17 Mar 2008 00:37:00 GMT На днях нужно было за короткое время решить одну несложную и довольно типичную задачу на django — построение формы профайла пользователя. Я не стал искать в закладках ссылки на старые известные how-to от мэтров-джангистов :-), а попробовал посмотреть что же нового и интересного у нас имеется в последней версии django (trunk). Итак, модель была приготовлена заранее, вопрос больше касался построения формы (через newforms ) пользовательского профайла. Итак, модель. class UserProfile(models.Model): user = models.ForeignKey(User, verbose_name=_('user'), unique=True, related_name="profile") country = models.ForeignKey(Country, verbose_name=_('country'), blank=True, null=True) city = models.CharField(verbose_name=_('city'), max_length=30, blank=True, null=True) post_zip = models.CharField(verbose_name=_('post zip'), max_length=10, blank=True) address = models.CharField(verbose_name=_('address'), max_length=250, blank=True) Обратите внимание, что профайл ссылается на модель User с unique=True . Это в принципе самый простой и работающий вариант расширения модели пользователя в django. Можно смело использовать для объекта User метод profile.get() . Например: from django.contrib.auth.models import User u = User.objects.get(username='test') profile = u.profile.get() Теперь для моделей User и UserProfile необходимо построить единую форму. Для каждой отдельной модели сделать это не проблема. А вот сделать «два в одном» не так просто. Итак, по порядку: Новенькое — широко используемые функции form_for_model и form_for_instance оказывается уже не актуальны. Они работают, но есть более новый и интересный метод получения формы для модели — ModelForm . В отличии от форм полученных через form_for_model и form_for_instance , формы от ModelForm можно наследовать (а вот это очень интересно в нашем случае!!!). Поэтому, как только эти два пункта появились в моей голове, я сразу же открыл Python-консоль и начал экспериментировать с кодом. Не уверен на 100%, что мое решение максимально красивое, но тем не менее оно вполне простое и аккуратное (особенно если учесть, что времени на «подумать» особо не было)... Итак кусочек моего forms.py ниже. from django.newforms.models import ModelForm from django.contrib.auth.models import User from django import newforms as forms from profile.models import UserProfile class ProfileForm(ModelForm): class Meta: model = UserProfile fields=('country', 'city', 'post_zip', 'address') class ProfileFormFull(ProfileForm): def __init__(self, *args, **kwargs): super(ProfileFormFull, self).__init__(*args, **kwargs) self.fields['first_name'] = User._meta.get_field('first_name').formfield() self.fields['last_name'] = User._meta.get_field('last_name').formfield() def save_user_data(self): if self.instance: user = self.instance.user user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] return user.save() else: raise instance.DoesNotExist Теперь мои комментарии к коду (что я делаю): Создаю форму ProfileForm из моей модели UserProfile . Наследую от ProfileForm новую форму ProfileFormFull , которую буду расширять для возможности редактирования двух моделей (User и UserProfile) в одной форме. Суть расширения в добавлении двух полей из модели User ( first_name и last_name ) и метода save_user_data который эти поля сохраняет в модель User. Остальные поля из модели UserProfile обрабатываются автоматически созданным методом save . При сохранении формы нужно вызывать два метода — save и save_user_data . Я специально оставил эту возможность для моего случая. Но вы можете сделать сохранение save_user_data внутри save , расширив его. Как выглядит код, который работает с этой формой: @login_required @render_to('profile/main.html') def profile_save(request): if request.method == 'GET': return HttpResponseRedirect(reverse('profile.views.profile_page')) profile, created = UserProfile.objects.get_or_create(user=request.user) form = ProfileFormFull(data=request.POST, instance=profile) if form.is_valid(): form.save() form.save_user_data() request.user.message_set.create(message="Your profile details saved.") return HttpResponseRedirect(reverse('profile.views.profile_page')) else: return {'profile': profile, 'profile_form': form, 'user': request.user} На этом пожалуй откланиваюсь. Был бы очень рад любым конструктивным замечаниям и вопросам в комментариях. Хотелось бы унифицировать кусок кода с формой (forms.py) и может вынести в отдельный сниппет . PS: обязательно почитайте документацию по ModelForm , интересно :-) Posted in статьи Tags code , django , how , ModelForm , newforms , profile , to , user Meta 10 comments , permalink , rss , atom Загрузка всех моделей в django shell автоматом 2 Posted by dobrych Thu, 10 Jan 2008 12:11:00 GMT Наткнулся на интересную заметку. Как автоматизировать загрузку всех моделей из INSTALLED_APPS при запуске django python shell (manage.py shell). from django.db.models.loading import get_models for m in get_models(): exec "from %s import %s" % (m.__module__, m.__name__) Оказывается очень удобно! :-) Оригинал — Peter Sheats’ Blog » Blog Archive » Autoloading Your Django Models Posted in заметки Tags django , model , python , shell Meta no trackbacks , 2 comments , permalink , rss , atom Линкотека №1 9 Posted by dobrych Tue, 08 Jan 2008 17:38:00 GMT Решил сменить свою del.icio.us ленту в сайдбаре на более-менее регулярный постинг интересных ссылок. А вот место в сайдбаре собираюсь заполнить блогроллом. Так что если хотите попасть в список — напишите мне на имейл или в комментарии свой сайт/блог. Добавляю на условии, что вы ставите на меня обратный линк. Итак интересное, что я «нарыл» на просторах интернета за последние пару недель. StaticGenerator for Django — ссылка дня! очень полезный проект для django-разработчиков, может генерировать статический html вариант сайта из моделей, пользуясь методом get_absolute_url . Самое главное, что через сигналы он может автоматом обновлять html-страницы при изменении/добавлении объектов (т.е. буквально данных в базе). Evaluation of web based WYSIWYG-editors, test result 2007 — обзор онлайновых WYSIWYG редакторов (javascript и один на java), с него набрел на один интересный редактор (следующая ссылка). WYMeditor - web-based XHTML editor — простой интересный онлайн редактор, без возможности upload/insert images, но зато более семантичный и наглядный для тех, кто знает HTML. WYMstyle и css-boilerplate — css frameworks, хороши для веб проектов, когда у вас еще нет дизайна веб-сайта/веб-приложения, но вам нужно более-менее симпатично показать контент и функционал. Облегчают работу тем, кто не любит долгой возни с версткой. swfobject 2 — новая переработанная версия (на данный момент rc1) javascript библиотеки для включения в страницу flash/flex роликов или приложений. Кто еще не пробывал — советую, намного удобнее, чем писать кроссбраузерные теги и делать ручные проверки нужной версии flash. Еще можно почитать блог разработчиков — SWFFix Dev Blog . transdb — неплохая библиотека для локализации конента в django. Добавляет специальные многоязыковые текстовые поля в модель, что облегчает работу с базой и хорошо интегрируется с существующей системой i18n в django. PyAMF — Реализация на Python поддержки протокола обмена данными AMF (от Adobe) для клиент-серверного взаимодействия. Используется во flash и других проектах Adobe. Данные по этому протоколу передаются в бинарном виде, что более-продуктивно с точки зрения потребления траффика, автоматизирована сериализация/десериализация данных как на стороне сервера, так и клиента. Posted in заметки Tags css , django , editor , flash , i18n , javascript , link , python , swfobject , wysiwyg Meta no trackbacks , 9 comments , permalink , rss , atom Older posts: 1 2 Searching... О блоге Мысли, идеи, задачи и решения по веб-разработке. Взгляд с персональной позиции автора. Работа и вакансии по моим личным рекомендациям. Об авторе Зовут меня Илья. В рабочее время занимаюсь веб-разработкой. Интересуюсь новыми и модными веб-технологиями. Нерабочее время посвещаю семье, по возможности фотографии и музыке . Подробнее. Tags ajax conference css development django downshifting exception google javascript kiev life python rails ruby syntax typo uaweb update web xml Блогролл Amazon byteflow Маниакальный Веблог Подробно Appleworms Alpha-Beta-Release Blog Андрей Ясинецкий Собираю блогролл Свежие комментарии by LitnertJemniztrmz on Не изобретая велосипед by Debrirerboatt on Не изобретая велосипед by AddepeMaf on Не изобретая велосипед by GlapleDrawl on Не изобретая велосипед by Elizavetta on Не изобретая велосипед Archives September 2008 (3) July 2008 (3) June 2008 (4) May 2008 (2) April 2008 (2) March 2008 (5) February 2008 (2) January 2008 (4) December 2007 (2) November 2007 (2) October 2007 (3) September 2007 (2) August 2007 (4) June 2007 (1) May 2007 (1) April 2007 (3) February 2007 (1) January 2007 (3) December 2006 (4) November 2006 (4) October 2006 (4) September 2006 (3) Delicious/dobrych/webdev django-localeurl [whatwg] Dealing with UI redress vulnerabilities inherent to the current web Time breakdown of modern web design Page Inlink Analyzer asql - Apache SQL querying jsonserver Introducing the Django Debug Toolbar OAuth Playground Using Python and Stompserver to Get Started With Message Queues Nice example about message queuing in python with stompserver django-granular-permissions Row-level permissions Плюшки Рекламка © livedev.org / powered by typo / styled with clerkly