Ежемесячные архивы: Февраль 2011

Связанные списки select в django (ajax select linked)


Потратив часа 3 на поиск рабочего решения связанных полей (Это когда в зависимости от категории нужно показывать под категорию) спешу поделиться чтоб не забыть

в urls.py

[cc lang=”python”](r’^ajax/categ/$’, ‘proj.list.views.feeds_subcat’),[/cc]

во Вьюхе
[cc lang=”python”]
def feeds_subcat(request):
from django.core import serializers
json_subcat = serializers.serialize(“json”, SubCategory.objects.filter(category_name=request.GET[‘id’]))
return HttpResponse(json_subcat, mimetype=”application/javascript”)[/cc]

Примерно рассказываю что там происходит
В модели SubCategory выбираем имя субкатегории, которая соответствует ид_категории, что к нам привалило.
всё это оборачиваем в JSON попутно подгружаем библиотеки для этих дел.
и отправляем прямо в формате js всё обратно.

теперь создаём ещё один js файл называем его как душе угодно (и не забываем подключить)
[cc lang=”html”][/cc]
[cc lang=”JavaScript”]
$(function(){
$(“select#id_categ”).change(function(){
$.getJSON(“/ajax/categ/”,{id:+$(this).val()}, function(j) {
var options = ‘‘;
for (var i = 0; i < j.length; i++) { options += '‘;
}
$(“#id_sub”).html(options);
$(“#id_sub option:first”).attr(‘selected’, ‘selected’);
$(“#id_sub”).attr(‘disabled’, false);
})
$(“#id_categ”).attr(‘selected’, ‘selected’);
})
})[/cc]

Что он делает?
находит элемент select с id = “id_categ”
При изменении которого вызывает функцию $.getJSON, которая долбится по урле /ajax/categ/ гет запросом и параметром ?id=то_что_выбрано
Если всё отлично выполняется функция j
Которая и меняет значение во втором селекте.
#id_categ – ИД_селекта категории
#id_sub – ИД_селекта подкатегории

django devserver статические файлы ( django devserver static files)

Во время разработки нужно чтоб статика обрабатывалась dev сервером, всякие файлы стилей js и т.п.

Для решения этой задачи я использую вот это:

urls.py
[cc lang=”python”](r’^static/(?P.*)$’, ‘django.views.static.serve’, {‘document_root’: ‘/home/django/list/static’}),[/cc]
в корне проекта создаю каталог static, в котором создаю подкаталоги js images style и т.п

Django ajax пример ( django ajax autocomplite)

Продолжаю понемногу разбираться в Django

Дошло до авто заполнения полей, пару дней перечитывал все “Интернеты” о разных вариантах и методах, о готовых примерах и т.п.

И так начнём я воспользовался jQuery плагином Autocomplete
Всё это я брал вот тут
Плагин совсем не полный ищет так себе похоже просто старый.
Поэтому идём и берём самый новый ..

тут оно будет работать без основного jQuery

Но на других страницах проекта, есть более полные версии и более красивые.
Вот их и качаем
Из них нам нужны
в папочку css кидаем
[cc lang=”html”]indicator.gif
jquery.autocomplete.css[/cc]
в папочку js кидаем
[cc lang=”html”]jquery-1.5.min.js
jquery.autocomplete.min.js[/cc]

Поехали, предположим, что у нас есть в urls.py

[cc lang=”python”](r’^asearch/$’, ‘man.views.ajax_search’),[/cc]

man.views.ajax_search – я думаю рассказывать не надо, что это своё приложение и Вьюха его

во views.py
[cc lang=”python”]
def ajax_search(request):
if request.method == ‘GET’:
GET = request.GET
if GET.has_key(‘q’):
q = request.GET.get( ‘q’ )
search = Task.objects.all()
results = search.filter(name__contains = q)
matches = “”
for result in results:
matches = matches + “%s\n” % (result.name)
return HttpResponse(matches, mimetype=”text/plain”)
[/cc]

В данном примере мы будет общаться через обычный get запрос.
Можно сделать “не обычным”
например так
[cc lang=”python”]
if request.is_ajax():
q = request.GET.get( ‘q’ )[/cc]

Но об этом попробую ещё написать, когда буду более тонко в этом разбираться
В модели Task мы делаем поиск по полю “name”.
Потом всё это выстраиваем в красивый список с переносами строк
в итоге в переменной matches у нас будет уже структурированный список.

Теперь на стороне клиента.

Во первых подключаем плагин со стилями и jquery

[cc lang=”html”]

[/cc]

Добавим простую функцию jQ
[cc lang=”html”]

[/cc]
Тут мы говорим плагину: находим элемент с id=”q1″ и будем с ним работать.
А всё запросы отправлять на урл “/asearch/”

дальше собственно сам элемент

[cc lang=”html”][/cc]

Вот собственно и всё.

django-registration Пример

Мопед не мой, был в песочнице на хабре, потом в кэше гугла, чтоб совсем не потерялся решил оставить себе, был бы у меня инвайт, обязательно выслал, а так пока ещё не заслужил 🙁

В интернете есть много разрозненной информации о django-registration и о расширении стандартной модели Users. Однако, тотального примера, которое позволило бы новичку вникнуть как реализовать задуманную им логику регистрации нет. Я попробовал восполнить этот пробел.

Поставим себе следующие техническое задание:

* Во время регистрации пользователь заполняет дополнительные поля.
* При отправке формы — вся информация сохраняется в профайле, и на почту высылается письмо с ссылкой для активации.
* При переходе по ссылке пользователь активирует свою учетную запись, автоматически авторизуется на сайте, и перенаправляется на определенную страницу.

Сразу отметим что по умолчанию django-registration не включает в себя сохранение дополнительных полей, и после активация записи приходится вводить свой логин и пароль для авторизации.

Расширение модели User

Расширять модель пользователя мы будем соединением нашей модели Profile с стандартной моделью User посредством поля AutoOneToOneField. Подробнее об этом здесь.

Для начала создадим новое приложение profile:
[cc lang=”python”]django-admin.py startapp profile[/cc]
Заходим в созданную папку profile, и открываем для редактирования файл models.py. В нашем примере, мы расширим модель пользователя полем проффесия, при чем посетитель сайта при регистрации будет выбирать проффесию из списка. Для удобного редактирования этого списка, мы вынесем его в отдельную модель Work. И так, models.py у нас обрастет таким кодом:

[cc lang=”python”]#profile/models.py
# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from habr.profile.fields import AutoOneToOneField

class Work(models.Model):
work = models.CharField(max_length = 100, verbose_name = ‘Работа’)

class Profile(models.Model):
user = AutoOneToOneField(User, related_name=’profile’, verbose_name=(‘User’), primary_key=True)
work = models.ForeignKey(Work, verbose_name = ‘Вид деятельности’)
[/cc]

Мы подключаем поле AutoOneToOneField. Создадим в каталоге profile файл fields.py с таким кодом:

[cc lang=”python”]#profile/fields.py
# -*- coding: utf-8 -*-

from django.db.models import OneToOneField
from django.db.models.fields.related import SingleRelatedObjectDescriptor

class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
def __get__(self, instance, instance_type=None):
try:
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
except self.related.model.DoesNotExist:
obj = self.related.model(**{self.related.field.name: instance})
obj.save()
return obj

class AutoOneToOneField(OneToOneField):
def contribute_to_related_class(self, cls, related):
setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
[/cc]

Осталось добавить приложение в INSTALLED_APPS (файл настроек settings.py), а также указать директиву AUTH_PROFILE_MODULE:

[cc lang=”python”]#settings.py
INSTALLED_APPS = (
##
‘habr.profile’,
##
)
AUTH_PROFILE_MODULE = ‘habr.profile.profile’

[/cc]

Этот этап пройден, выполняем python manage.py syncdb и смотрим как создаются новые таблицы.

Прикручиваем и кастомизируем django-registration

Django-registration — это модуль который позволяет легко реализовать на сайте регистрацию с авторизацией по электронной почте (либо без онной). Достаточно подробно о её установке написано здесь, мы же пробежимся по основным нюансам, и займемся кастомизацией.

Для установки django-registration достаточно просто скачать её отсюда, разархивировать архив и положить папку registration в корневую папку вашего проекта. Однако, так поступать категорически не рекомендуется, лучше воспользоватся утилитами установки easy-install либо pip. Но тут есть один нюанс, если просто выполнить:
[cc lang=”bash”]easy_install -Z django-registration[/cc]

установится версия 0.7, которая не поддерживает очень удобный механизм — сигналы. Поэтому, чтобы посредством easy-install установить последнюю версию 0.8, необходимо выполнить:
[cc lang=”bash”]easy_install-2.6 cdn.bitbucket.org/ubernostrum/django-registration/downloads/django-registration-0.8-alpha-1.tar.gz[/cc]
(Возможно, когда вы будете читать эту статью, эта версия не будет последней актуальной, так что не забудьте проверить)
После этого следует добавить в INSTALLED_APPS — ‘registration’, а также обязательную директиву ACCOUNT_ACTIVATION_DAYS — которая устанавливает в течении скольки дней пользователь может активировать свою запись:

[cc lang=”python”]#settings.py
INSTALLED_APPS = (
##
‘habr.profile’,
‘registration’,
##
)
AUTH_PROFILE_MODULE = ‘habr.profile.profile’
[/cc]
Далее необходимо сделать привязку URL, для этого редактируем файл urls.py, добавляя в urlpatterns строчку:
[cc lang=”python”]url(r’^accounts/’, include(‘registration.backends.default.urls’)),[/cc]
Теперь для работы осталось только создать шаблоны для регистрации, активации и т.д. Это опять же подробно описано здесь, не будем повторятся.
После этого обновляем базу данных (python manage.py syncdb) и можно тестировать регистрацию. Не забудьте запустить почтовый сервер.

Теперь мы подошли к самому интерестному — добавим поля профиля в регистрационную форму, и несколько кастомизируем регистрацию.

Унасследуем стандартную форму модуля django-registration и добавим в неё наши поля. Создаем forms.py в папке profile:

[cc lang=”python”]#profile/forms.py
# -*- coding: utf-8 -*-

from django import forms
from registration.forms import RegistrationFormUniqueEmail
from habr.profile.models import Work

WORK_CHOICES = [
(work.id, work.work) for work in Work.objects.all()
]

class RegistrationFormProfile(RegistrationFormUniqueEmail):
work = forms.ChoiceField(choices=WORK_CHOICES, label = ‘Работа’)

[/cc]
Обратите внимание как заполняется список выбора. При такой реализации при добавлении в таблицу Work новых строк прийдется перезагружать джангу, но зато список кешируется, и не будет происходить выполнения запроса к базе данных каждый раз при выводе формы. Такой вариант подходит когда таблицу не планируется часто изменять.

Теперь нам надо чтобы бэкэнд django-registration использовал нашу форму вместо своей по умолчанию, для этого в urls.py перед
[cc lang=”python”]url(r’^accounts/’, include(‘registration.backends.default.urls’)),[/cc]
добавим
[cc lang=”python”]
url(r’^accounts/register/$’, ‘registration.views.register’, {‘backend’: ‘registration.backends.default.DefaultBackend’, ‘form_class’:RegistrationFormProfile,},
name=’registration_register’),[/cc]

И имортируем форму:

[cc lang=”python”]from habr.profile.forms import RegistrationFormProfile[/cc]

Раньше приходилось переписывать у формы метод save(), в django-registration 0.8 появилась возможность повесить сигнал на создание юзера. Также сразу повесим сигнал на активацию юзера, для того чтобы сразу провести авторизацию.

Создадим signals.py в папке profile:

[cc lang=”python”]#profile/signals.py
# -*- coding: utf-8 -*-

from registration.signals import user_registered, user_activated
from habr.profile.models import Profile
from forms import RegistrationFormProfile
from django.contrib import auth

def user_created(sender, user, request, **kwargs):
form = RegistrationFormProfile(request.POST)
profile = Profile(user=user, work_id = int(form.data[‘work’]))
profile.save()

def login_on_activation(sender, user, request, **kwargs):
user.backend=’django.contrib.auth.backends.ModelBackend’
auth.login(request,user)

user_activated.connect(login_on_activation)
user_registered.connect(user_created)

[/cc]

Теперь осталась импортировать эти функции в urls.py:

[cc lang=”python”]from habr.profile.signals import *
[/cc]
Остался последний штрих — мы хотим чтобы после регистрации пользователь попадал на определенную целевую страницу, для этого можно просто повесить представление на url accounts/activate/complete/:

[cc lang=”python”]url(r’^accounts/activate/complete/$’, ‘gamb.profile.views.redirect_after_activation’),[/cc]

Техническое задание выполнено!

pindgin facebook /usr/share/pixmaps/pidgin/protocols/16/facebook.png

Любимая убунту недавно порадовала рекурсией, пыталась перустановить пакет pidgin и ей этого не удавалось, не могла удалить
/usr/share/pixmaps/pidgin/protocols/16/facebook.png вот этот файл, ручное удаление не помогало, дело в том, что последняя версия pidgin конфликтует с пакетом pidgin-facebookchat

Вот после его удаления всё наладилось