API do wklej.org tymczasowo wyłączone. [UPDATE]

Poniedziałek, 2011-12-05 @ 19:25 | edit
UPDATE: API Zostało ponownie uruchomione Z góry przepraszamy za wszelkie utrudnienia, ale ze względu na przeprowadzana przez nas selektywne testy wydajnościowe, musimy tymczasowo wyłączyć dostęp do dodawania wklejek via XMLRPC na wklej.org. Mówiąc prostszymi słowami: testujemy dlaczego ostatnio wklej zaczął zjadać zbyt duże ilości RAMu. Przewidywany downtime ? od poniedziałku, 21.11 20:30 do *wtorku, 22.11 godzina 20:00*

Testowanie aplikacji w django z migracjami w south.

Poniedziałek, 2011-12-05 @ 19:25 | edit
Ostatnio zacząłem zgłębiać temat testów w django (napiszę o tym osobny, dłuższy post), ale od razu pojawił się pewien problem. Przy kreowaniu testowej bazy danych nie generowały się tabele dla aplikacji, które miały migracje z South.
DatabaseError: (1146, "Table 'test_db1.users_userprofile' doesn't exist")

.
----------------------------------------------------------------------
Ran 1 test in 1.590s

OK
Jak sobie z tym poradzić?
SOUTH_TESTS_MIGRATE = False
... do settings.py Dziękuje, dobranoc.

Problem z dostępem do wstaw.org

Poniedziałek, 2011-12-05 @ 19:25 | edit
Dzisiaj od ~południa można było doświadczyć pewnych problemów z dostępem do serwisu wstaw.org objawiającego się takim oto ekranem: Domain has been redirected Problemem okazały się wpisy do whois w godaddy, po zaktualizowaniu których godaddy uwolniło domenę, i problem powinien zniknąć maksymalnie w ciągu kilku godzin. Dziękujemy za korzystanie z serwisu.

Caught AttributeError while rendering: 'BlockNode' object has no attribute 'context

Poniedziałek, 2011-12-05 @ 19:25 | edit
Być może uratuje komuś kilka(naście) minut z googlania. Błąd z tytułu lubi pojawiać się np. wtedy gdy próbujemy odpalić {{ block.super }} w szablonie, który z niczego nie dziedziczy.

How to authenticate in Django via urllib2?

Poniedziałek, 2011-12-05 @ 19:25 | edit
Let's say you want to write a python script, using urllib2 to access some @login_required protected typical django website, with django.contrib.auth authentication and default csrf protection. In order to do this, you have to first login, and then keep the cookie with session id you received. Also, you need to keep in mind that csrf will raise a 403 if you would try to POST to the page without csrf_token in your POST data. First you have to do some initial setup that will later allow you to use cookies:
import urllib, urllib2
import cookielib

cj = cookielib.CookieJar()

opener = urllib2.build_opener(
    urllib2.HTTPCookieProcessor(cj), 
    urllib2.HTTPHandler(debuglevel=1)
)
HTTPHandler(debuglevel=1) part is actually optional, in this case it would just print more data that you might be interested in (headers mostly). Now you use your shiny new opener to open a login page and grab a csrf token from it:
from lxml import html
login_form = opener.open(login_url).read()
csrf_token = html.fromstring(login_form).xpath(
    '//input[@name="csrfmiddlewaretoken"]/@value'
)[0]
Then you create dictionary with username, password and newly grabbed token:
# make values dict
values = {
    'username': username,
    'password': password,
    'csrfmiddlewaretoken': csrf_token,
}

# Convert to params
params = urllib.urlencode(values)
Then you can login:
login_page = opener.open(login_url, params)
print login_page.read()
And check out some sites that needs authentication:
staff_page = opener.open(staff_url)
print staff_page.read()
Enjoy!

O nadpisywaniu pól i polami.

Poniedziałek, 2011-12-05 @ 19:25 | edit
Jak wszyscy wiemy Django umożliwia dziedziczenie modeli w dodatku na klika sposobów. Jednak ma pewne ograniczenia. Nie można np. nadpisać pola z modelu bazowego nowym polem. Jak czytamy w dokumentacji:
This restriction only applies to attributes which are Field instances. Normal Python attributes can be overridden if you wish. It also only applies to the name of the attribute as Python sees it: if you are manually specifying the database column name, you can have the same column name appearing in both a child and an ancestor model for multi-table inheritance (they are columns in two different database tables).
Jendakże... Co się stanie kiedy będziemy chcieli nadpisać nie pole, a polem? Np. tworząc pole o nazwie takiej samej jak @property z modelu bazowego? Odpowiedź: Otrzymamy AttributeError. o treści "can't set attribute". Pełne case study dostępne jako ticket na code.djangoproject.com.

Szczęśliwego nowego.

Poniedziałek, 2011-12-05 @ 19:25 | edit
W tym roku nieco zaspaliśmy i zapomnieliśmy złożyć zarówno życzeń świątecznych jak i noworocznych. Dlatego składamy je właśnie teraz. Przynajmniej te noworoczne. A więc: "Szczęśliwego Nowego Roku". Ze spraw organizacyjnych ? wczoraj około północy na dłuższą chwilę zostały wyłączone wszystkie nasze serwisy, ale bez paniki ? wszystko już działa tak jak powinno. Powodem chwilowej przerwy w dostawie contentu była zmiana dedyka na którym hostujemy nasze projekty. Co prawda dalej hostujemy się w ovh, jednak maszyna, którą teraz zajmujemy trochę różni się od poprzedniej, a ponieważ mamy na niej dużo miejsca i niewykorzystanych zasobów ? jeżeli potrzebujesz któregoś z nich ? skontaktuj się z nami ? Na pewno coś wymyślimy. ;) W Nowym Roku planujemy również kilka zmian: mamy nadzieję, że znajdziemy czas na usprawnienie działania naszych flagowych serwisów ? wklej.org i wstaw.org oraz, że cogdziejak.pl zostanie wreszcie publicznie otwarty. W zanadrzu mamy również plan na conajmniej jeden nowy i pożyteczny serwis, a więc stay tuned. Na blogu również pojawią się nowe teksty, m.in kontynuaacja serii o aplikacjach wielokrotnego użytku i koszernych praktykach. Jednym słowem ? Idzie Nowe, i jest to dobry moment na dodanie naszego kanału RSS do czytnika.

Sortowanie wersji w Pythonie.

Poniedziałek, 2011-12-05 @ 19:25 | edit
Niech g będzie listą stringów wyglądających jak nr wersji jakiegoś pakietu:
g = ["1.1", "1.2", "1.10", "1.6", "1.65", "1.59", "1.23"]
Jak wykorzystując pythona posortować tę listę tak aby otrzymać wersje chronologicznie?
['1.1', '1.2', '1.6', '1.10', '1.23', '1.59', '1.65']
Wykorzystujemy do tego moduł distutils.version:
In [1]: from distutils.version import StrictVersion

In [2]: g = ["1.1", "1.2", "1.10", "1.6", "1.65", "1.59", "1.23"]

In [3]: f = [StrictVersion(x) for x in g]

In [4]: sorted(f)
Out[4]: 
[StrictVersion ('1.1'),
 StrictVersion ('1.2'),
 StrictVersion ('1.6'),
 StrictVersion ('1.10'),
 StrictVersion ('1.23'),
 StrictVersion ('1.59'),
 StrictVersion ('1.65')]

In [5]: [str(x) for x in sorted(f)]
Out[5]: ['1.1', '1.2', '1.6', '1.10', '1.23', '1.59', '1.65']
Szczególne podziękowania dla Restless Being za zwrócenie uwagii na bibliotekę. :)

Django i MySQL a UTF8.

Poniedziałek, 2011-12-05 @ 19:25 | edit
Kolejny ultrakrótki wpis, który w jednym akapicie tłumaczy co zrobić, gdy pojawi się nam taki error:
Incorrect string value: '\xC5\x9B\xC4\x87\xC5\xBA...'
 for column 'first_name' at row 1
(standardowy Exception (konkretniej Warning) na żółto szarym tle. Pogrubione elementy mogą się różnić). Rozwiązanie jest proste. Podczas tworzenia bazy trzeba dodać:
CREATE DATABASE foobardb DEFAULT CHARACTER SET utf8;
I... tyle. Dziękuje za uwagę. :)

Z archiwum Django: Znikające elementy listy.

Poniedziałek, 2011-12-05 @ 19:25 | edit
W ?Archium X? Mulder i Scully prowadzili śledztwa, które nie dały się wyjaśnić na drodze konwencjonalnego rozumowania (via wikipedia). Nie inaczej jest podczas codziennych potyczek z programowaniem (i nie tylko). Czasami zdarzają się przypadki, które na pierwszy rzut oka powinny zachowywać się całkiem inaczej.... Weźmy przykładowo formę (np. ModelForm) prezentującą relacje Many to many. W momencie gdy submitujemy taką formę, wewnątrz request.POST (lub form.data) powinniśmy znaleźc listę numerów id obiektów, które wybraliśmy: np. taką:
... 'permissions': [u'1', u'5', u'18', u'24'], ...
Idąc tym tokiem rozumowania, wewnątrz request.POST['permissions'] powinna się znaleźć owa lista. Ale czy na pewno?

I tak, i nie....

Tak bo tam faktycznie, będzie lista, ale jeżeli spróbujemy wyciągnąć ją w pokazany wyżej sposób otrzymamy co innego:
>>> print request.POST['permissions']
24
Teraz pytanie ? gdzie podział się wiersz przypisujący 24 do 'permissions' zamiast powyższej listy? Nigdzie. Wystarczy zapamię?ać, że request.POST to nie jest zwykły słownik a QueryDict czyli bazujący na słowniku inny typ danych i w przypadku list __getitem__ zwróci tylko ostatni jej element. Aby pobrać całą listę należy to zrobić tak:
>>> print request.POST.getlist('permissions')
[u'1', u'5', u'18', u'24']
I to by było na tyle...