Jun 30, 2011

Request useful methods

request.path # the full path, not including the domain "/hello/" but including the leading slash 
request.get_host() # the host (i.e., the “domain,” in common "127.0.0.1:8000" or parlance) "www.example.com"
request.get_full_path() # the path, plus a query string (if available) "/hello/?print=true"
request.is_secure() # True if the request was made via HTTPS; True or False otherwise, False 

Jun 29, 2011

Find the real location of the exception

The problem with Django is that there are certain circumstances where it will hide the actual error message and traceback and replace it will a higher level exception, but with the traceback then being where that higher level exception was raised. This is one such case. To try and find the real location of the exception add the following to your WSGI script file.

import traceback 
import sys 
def dump_exception(callable): 
    def wrapper(*args, **kwargs): 
        try: 
            return callable(*args, **kwargs) 
        except: 
            traceback.print_exception(*sys.exc_info()) 
    return wrapper 
import django.core.urlresolvers 
urlresolvers.get_callable = dump_exception(urlresolvers.get_callable) 

This wraps the call which is doing the lookup and will dump out the error message it raises before the traceback gets thrown away.

Hg or git branch in bash prompt

in ~/.bashrc (Ubuntu 12.04)
hg_branch() {
    hg branch 2> /dev/null | \
        awk -v "clrp=$txtpur" -v "clrr=$txtrst" \
            '{ print clrp "@hg:" $1 clrr}'
}
hg_dirty() {
    [ $(hg status 2> /dev/null | wc -l) != 0 ] && \
        echo -e "${txtred}*${txtrst}"
}

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\W$(hg_branch)$(hg_dirty)\$ '
fi
then your prompt will looks like:
someproject$ vi /home/alexey/.bashrc  # make changes above
someproject$ source /home/alexey/.bashrc 
someproject@hg:liveserver$  # liveserver is current brunch
someproject@hg:liveserver$ hg branch
liveserver
someproject@hg:liveserver$ touch blabla
someproject@hg:liveserver*$  # asterisk indicates that VCS has changes
someproject@hg:liveserver*$ hg st
? blabla
Also you can do the same for git:
git_branch() {
    git branch --no-color 2> /dev/null | grep "*" |\
        awk -v "clrp=$txtpur" -v "clrr=$txtrst" \
            '{ print clrp "@git:" $2 clrr}'
}
git_dirty() {
    [ $(git status --short 2> /dev/null | wc -l) != 0 ] && \
        echo -e "${txtred}*${txtrst}"
}

Jun 25, 2011

Изменение названия модуля в django admin

class Stuff(models.Model):
    class Meta:
        verbose_name = u'The stuff'
        verbose_name_plural = u'The bunch of stuff'
django admin использует app_label.title() поэтому мы можем использовать небольшой хак: подкласс str с переопределенным методом title:
class string_with_title(str):
    def __new__(cls, value, title):
        instance = str.__new__(cls, value)
        instance._title = title
        return instance

    def title(self):
        return self._title
и в итоге получаем:
class Stuff(models.Model):
    class Meta:
        app_label = string_with_title("stuffapp", "The stuff box")
        # 'stuffapp' is the name of the django app
        verbose_name = 'The stuff'
        verbose_name_plural = 'The bunch of stuff'

См. также: Rename django admin app name and breadcrumbs

Jun 24, 2011

Полезные функции в Django

В Django существует куча полезных функций и классов, которые помогают выполнять простые и полезные действия раз от разу. Предлогаю Вам свое видение этого списка:
django.utils.datastructures.SortedDict
django.utils.datastructures.MultiValueDict
По умолчанию в Python объект dict не поддерживает сортировку ключей и несколько значений для одного ключа. Именно поддержку этих возможностей дают перечисленные выше классы. Например, поддержка GETPOSTREQUEST массивов в объекте request реализована в виде MultiValueDict объектов.
django.utils.dates
Этот модуль содержит разнообразные массивы, которые используются для печати SelectDateWidget'а.
django.utils.encoding.force_unicode
Переводит любой Python объект в unicode. Так же переводит в unicode любую модель Django у которой есть метод __unicode__.
django.utils.html.clean_html
Очищает переданный в функцию HTML строку, а именно:
  • Конвертирует <b> и <i> в <strong> и <em>.
  • Правильно кодирует все амперсанды.
  • Удаляет все "target" аттрибуты с тегов <a>.
  • Конвертирует явно заданные баллетсы (bullets) в неупорядоченные HTML списки.
  • Удаляет из текста фрагменты "<p>&nbsp;&nbsp;</p>", но только если они находятся в конце текста.
django.utils.html.urlize
Переводит все ссылки в тексте в <a> тэги.
django.utils.safestring.mark_safe
Обозначает любой строковой объект, как безопасный для того, чтобы он мог был беспрепятственно распечатан в шаблоне без эскейпинга символов.
django.utils.text.get_text_list
Для описания работы этой функции и doctest'а хватит:
>>> get_text_list(['a', 'b', 'c', 'd'])
u'a, b, c or d'
>>> get_text_list(['a', 'b', 'c'], 'and')
u'a, b and c'
>>> get_text_list(['a', 'b'], 'and')
u'a and b'
>>> get_text_list(['a'])
u'a'
>>> get_text_list([])
u''

Jun 22, 2011

Dkim

pydkim

Python module that implements DKIM (DomainKeys Identified Mail) email signing and verification. It also provides helper scripts for command line signing and verification.

Snippet

from django.core.mail.backends.smtp import EmailBackend
from django.conf import settings
import dkim # http://hewgill.com/pydkim

class DKIMBackend(EmailBackend):
    def _send(self, email_message):
        """A helper method that does the actual sending + DKIM signing."""
        if not email_message.recipients():
            return False
        try:
            message_string = email_message.message().as_string()
            signature = dkim.sign(message_string,
                                  settings.DKIM_SELECTOR,
                                  settings.DKIM_DOMAIN,
                                  settings.DKIM_PRIVATE_KEY)
            self.connection.sendmail(email_message.from_email,
                    email_message.recipients(),
                    signature+message_string)
        except:
            if not self.fail_silently:
                raise
            return False
        return True

Изменение размеров всех фото в папке

#!/bin/bash
for f in *.JPG
do
  NEWNAME=`basename ${f} .JPG`_OK.jpg
  echo $NEWNAME
  convert -resize '1024!x768' $f $NEWNAME
done

Jun 20, 2011

Fast Flex app compilation

/p/projects/networkingtv/flex_sdk/bin/fcsh
(fcsh) mxmlc -load-config+=flex-config.xml

Media

Videos

ffmpeg -i input.mpg -ar 22050 -ab 64 -f flv -s 320x240 -r 29.970 -b 1000k -y output.flv

-ar -- is the Audio sample rate ie, 11050, 22050, 44144, and 48000
-ab -- is the Audio Bitrate ie, 64Kbits, 128Kbits, 384Kbtis, etc.
-r ---- is the Frame Rate or fps of the finished video, ie 24, 25, 29.970 etc.
-b ---- is the Bitrate you want to set the flv video to ie, 360k, 1000k etc.

# better
mencoder input.mpeg -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell -oac copy -vf scale=360:240 -o output.avi

# worse
ffmpeg -i input.avi -b 1000 -s 640x480 -vcodec mpeg4 -r 30000/1001 output.avi

# or
ffmpeg -i M2U00009.MPG  -ar 44100 -ab 128k -s 720:480 -padtop 46 -padbottom 50 -padcolor 000000 -ss 00:00:40 -t 00:02:55  -f mp4 grok3.avi

# for android
https://help.ubuntu.com/community/AndroidVideoEncoding

Images

convert -resize '320x240!' 002.jpg thmb_002.jpg

Screenshot

sudo apt-get install scrot
scrot
# or
sleep 10 && scrot
# or
scrot -e 'mv $f /your/pictures'

Удаление элементов из списка

a=range(10);
for item in a:
    if item < 5:
        a.remove(item)
print a 

# Вернет [1, 3, 5, 6, 7, 8, 9]
Почему так происходит? Потому что при удалении элемента из списка, индекс не уменьшается. А значит, следующий элемент списка будет пропущен. Отчаявшись, люди идут на такие ухищрения:
i = 0
while i < len(a):
    if i < 5:
        del a[i]
    else:
        i += 1
Нам на помощь приходит такая замечательная функция как filter(func, a). Она создает новый список из элементов списка, для которым функция func(item) вернет истину.
filter(lambda x: x <= 5, a)
# Вернет [6, 7, 8, 9]
[i for i in a if i >= 5]
# Также вернет[6, 7, 8, 9], да и выглядит красивее.
print a # Список a остался неизменным

Итерация по спискам

for i in range(len(a)):
    print "Под номером %d находится элемент %s" % (i, a[i])
Это работает, но что мы сделали лишнего: посчитали длину списка и создали еще один список, с длиной равной длине списка a. Нас немного спасет xrange, но правильнее от этого не станет. Если вам и правда необходимы индексы элементов, используйте enumerate.
for i, item in enumerate(a):
    print "Под номером %d находится элемент %s" % (i, item)
enumerate(a) не создает лишних списков, он возвращает поочередно элементы списка в виде (<индекс>, <элемент>). Да и выглядит такая конструкция гораздо понятнее.

Encription (len=128)

import hashlib
o = hashlib.sha512("22222@aaa.com" + str(datetime.datetime.now()))
o.hexdigest()

MySQL

# dump
mysqldump db_name -uroot -p > ffff.sql
mysql db_name -uroot -p < ffff.sql 

# drop all tables
mysql -BNe "show tables" db_name | awk '{print "drop table " $1 ";"}' | mysql db_name

PostgreSQL

#dump 
# http://stackoverflow.com/questions/2893954/how-to-pass-in-password-to-pg-dump
pg_dump -U db_user db_name | gzip > dump.sql.gz
gunzip dump.sql.gz
psql -U db_user db_name -f -  < dump.sql

#create
#grant usage on *.* to uuuu@localhost identified by 'pppp';
grant all privileges on database DB_NAME to USER_NAME;

#priveleges
sudo vi /etc/postgresql/8.4/main/pg_hba.conf

local   all         postgres                          trust

#Show all tables
\dt
# create user
createuser -U postgres -P -S -D -R -e username

# create db
createdb -U postgres -E UTF8 -T template0 -e -O username database_name

Bare git

# на сервере
cd ~/
mkdir someproject.git
cd someproject.git
git init --bare ### old version is ### git init-db

# у себя (в директории с сырцами)
git remote add hosting ssh://someusername@somedomain.com:2200/home/someproject.git
git push hosting master

# снова на сервере
$ cd ~/
$ git clone ~/someproject.git

# создание бранча
git checkout -b somebranchname --track hosting/somebranchname

SSH без пароля

Сначала генерируется ключ:
ssh-keygen 
chmod 644 ~/.ssh/id_rsa.pub
ssh-agent bash
ssh-add
Затем он копируется на сервер:
cd ~/.ssh/ && ssh-copy-id -i id_rsa serveruser@host

Так же удобно прописать алиасы

Class-based views

class SomeFormView(TemplateResponseMixin, View):
    template_name = 'some_form.html'
 
    def get(self, request):
        form = SomeForm()
 
        return self.render_to_response({
            'form': form,
        })
 
    def post(self, request):
        form = SomeForm(request.POST)
 
        if form.is_valid():
            form.save()
            messages.success(request, 'Your form has been saved!')
 
        return self.render_to_response({
            'form': form,
        })
 
 
class AjaxThingView(View):
    # Note that I don't subclass the TemplateResponseMixin here!
 
    def get(self, request):
        return HttpResponse(status=404)
 
    def post(self, request):
        id = request.POST.get('id')
 
        # Do something with the id
        return HttpResponse('some data')

Выполняем тесты быстрее

import sys
if 'test' in sys.argv:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'test_database.sqlite'
    }

Перевод разных слов на разных языках в django

from django.utils.translation.trans_real import translation

trans_en = translation('en')
trans_es = translation('es')

print trans_en.ugettext('word')
print trans_es.ugettext('word')

Сached decorator for functions

from django.core.cache import cache
from hashlib import sha256

def cached(ctime=3600):
    def decr(func):
        def wrp(*args,**kargs):
            key = sha256(func.func_name+repr(args)+repr(kargs)).hexdigest()
            res = cache.get(key)
            if res is None:
                res = func(*args,**kargs)
                cache.set(key,res,ctime)
            return res
        return wrp
    return decr

Создание локальной копии документации Django

Запускаем командую строку и устанавливаем Sphinx:
sudo easy_install Sphinx
Внутри вашей директории с Django находим папку docs, заходим в нее и:
make html
Вот и все! Внутри docs выполняем:
_build/html/index.html

Watch what SQL queries Dango produces

from django.db import connection
print connection.queries
print connection.queries[-1]['sql']

Or in Django >= 1.3
import logging
l = logging.getLogger('django.db.backends')
l.setLevel(logging.DEBUG)
l.addHandler(logging.StreamHandler())

Using tshark
sudo tshark -Tfields -e mysql.query -i any -R 'mysql.query'
mysql -h 127.0.0.1 -u root -p

Test email

sudo python -m smtpd -n -c DebuggingServer localhost:25

Setup django environment in standalone script

from django.core.management import setup_environ
import settings
setup_environ(settings)

Quick and pritty iteration

qs = Item.objects.filter(...).values_list('title', 'amount', 'price')

for title, amount, price in qs:
    print title, amount
    total += amount * price

Django apps

Templates

django-dbtemplates - templates in database

CMS

django-dbtemplates - templates in database

Testing

needle - checks that CSS renders correctly by taking screenshots of portions of a website and comparing them against known good screenshots

Translation

django-rosetta - .po files (admin interface, suggestions via Google Language)
django-nani - simple, predictable and compatible multilingual database contents

Log

django-sentry - real-time logging in admin
django-timelog - performance logging middlware and analysis tools
django-peavy - application for capturing logging to a database

Sql

django-unjoinify - a library for efficiently retrieving deeply-nested data sets
django-queryset-transform - experimental method for QuerySets, for clever lazily evaluated optimisations
django-qmixin - app for extending managers and the querysets they produce

Social

django-twitter-users - sign in with Twitter

Settings

gargoyle -  a platform which allows you to switch functionality of your application on/off

Tasks

celery - an asynchronous task queue/job queue based on distributed message passing

Form

django-uni-form

Newsletter

emencia-django-newsletter - sending newsletter by email to a contact list

Debugging

django-debug-toolbar
django-dtpanel-htmltidy - panel for Django Debug Toolbar which display HTML Validation errors

Jun 17, 2011

SPF пример

Полезные статьи

Вот что получилось для подковы:


SPF Record Testing Tools

Как в администрировании Django сделать action без обязательного выбора чекбокса

Есть action создания контактов для emencia-django-newsletter из ордеров

def make_mailing_list_all(self, request, queryset):
        from emencia.django.newsletter.models import Contact
        from emencia.django.newsletter.models import MailingList

        subscribers = []
        for order in OrderRecurring.objects.filter(status='active'):
            contact, created = Contact.objects.get_or_create(email=order.customer_email,
                                                           defaults={'first_name': order.customer_first_name,
                                                                     'last_name': order.customer_last_name,
                                                                     'content_object': order})
            subscribers.append(contact)
        new_mailing = MailingList(name='All Order recurrings mailing list',
                                  description='New mailing list created from all order recurrings')
        new_mailing.save()
        new_mailing.subscribers.add(*subscribers)
        new_mailing.save()
        self.message_user(request, '%s succesfully created.' % new_mailing)
    make_mailing_list_all.short_description = _('Create a mailing list for all active recurring orders')

    actions = ['make_mailing_list_all',]


Стандартно, если в списке не выбран ни один чекбокс, action не срабатывает. Нужно переписать метод admin.ModelAdmin.response_action:


    def response_action(self, request, queryset):
        from django.contrib.admin import helpers
        try:
            action_index = int(request.POST.get('index', 0))
        except ValueError:
            action_index = 0

        data = request.POST.copy()
        data.pop(helpers.ACTION_CHECKBOX_NAME, None)
        data.pop("index", None)

        try:
            data.update({'action': data.getlist('action')[action_index]})
        except IndexError:
            pass

        action_form = self.action_form(data, auto_id=None)
        action_form.fields['action'].choices = self.get_action_choices(request)

        if action_form.is_valid():
            action = action_form.cleaned_data['action']
            func, name, description = self.get_actions(request)[action]

            selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)
            ### CHANGED ###
            if not selected:
                if action == u'make_mailing_list_all':
                    pass
                else:
                    return None
            else:
                queryset = queryset.filter(pk__in=selected)

            response = func(self, request, queryset)
            ### END CHANGED ###

            if isinstance(response, HttpResponse):
                return response
            else:
                return HttpResponseRedirect(".")