Komiksy w sieci
Wczoraj wieczorem dokręciliśmy ostatnie śrubki w drugim z cyklu
projektów-w-tydzień. Tym razem z lekkim poślizgiem, w planach
mieliśmy zamknięcie prac w zeszłym tygodniu, w praktyce –
rzeczywiście intensywne prace zaczęliśmy w piątek, skończyliśmy
wczoraj (środa). Pierwszy
użytkownik powoli kończy przeprowadzkę.
Nowy serwis to WebComicsPot,
narzędzie do możliwie prostego publikowania w sieci komiksów, także
wielojęzycznych. Założenia były takie: samo umieszczenie plansz w
sieci jest proste i tanie, kłopotem jest za to złożenie sensownego
interfejsu pozwalającego na ich przeglądanie i przełączanie się między
tłumaczeniami. WebComicsPot rozwiązuje właśnie ten kłopot.
Jak w favpico, obsługa jest
uproszczona do granic możliwości: autor podaje tylko listę adresów pod
którymi znajdują się kolejne plansze. Serwis zakłada, że każdy adres
zawiera datę w formacie RRRR-MM-DD. Dodatkowo możliwe jest wklejenie
w stronę komiksu swojego kodu HTML i dodanie arkusza styli CSS.
Jednocześnie, to jest nasz pierwszy serwis wspierający OpenId – koniec z
wymyślaniem kolejnych haseł
Coś o stronie technicznej i organizacyjnej; zaletą tak małych
projektów jest to, że można w krótkim czasie sprawdzić w praktyce
sporo nowych narzędzi: jeśli się sprawdzą to świetnie, jeśli nie – to
upośledzają tylko jeden drobny projekt, nie ma sensu go przepisywać.
Tym razem znalazłem sporo przydatnych rzeczy.
Django-authopenid
zachowuje się bardzo sensownie, wymagała tylko drobnych poprawek
(które muszę jeszcze spakować w jeden sensowny diff i wysłać).
Instant Django to
świetny sposób na udostępnienie serwisu nieprogramiście
(np. grafikowi) pod Windows – zawiera, w jednej paczce, 2.5, django, sqlite, dość sensowny edytor tekstu i
parę skryptów które odpowiednio konfigurują środowisko. Wystarczy
dodać skrypt uruchamiający serwer (z syncdb przed startem), nauczyć
grafika korzystać z TortoiseSVN
i już, właśnie załatwiliśmy stronę techniczną współpracy.
FeedParser i FeedJack – świetne biblioteki do
obsługi RSS, używałem
ich już wcześniej w Planemoo. Tym razem FeedParser przydał się też do
czyszczenia kodu HTML wpisywanego przez autora komiksu: ze względów
bezpieczeństwa serwis usuwa część konstrukcji.
Cssutils
– podobnie jak w przypadku HTML, możliwość wpisania
dowolnego kodu CSS to dziura bezpieczeństwa ze względu na @import i
javascript w adresach. Sam cssutils nie potrafi tego wyczyścić, ale
wystarczyło utworzyć własną podklasę CSSSerializer, żeby usunąć i
@import, i podejrzane adresy:
URL_WITH_CALL_RE = re.compile(r'^url[(]["\']https?://\S+$') class SanitizingSerializer(cssutils.CSSSerializer): """ Overrides some stuff in CSSSerializer to make it safer. 1. disallow ALL URLs not starting with 'http://' or 'https://' 2. remove @imports """ def do_css_CSSValue(self, cssvalue): if cssvalue and isinstance(cssvalue, CSSPrimitiveValue): if cssvalue.primitiveType == CSSPrimitiveValue.CSS_URI: if not URL_WITH_CALL_RE.match(cssvalue._value): return u'url("")'; return super(SanitizingSerializer, self).do_css_CSSValue(cssvalue) def do_CSSImportRule(self, rule): return u'' cssutils.setSerializer(SanitizingSerializer())
Django zawiera bibliotekę do komentarzy, bardzo przydatną ale z
paroma ograniczeniami; przeszkadzał mi, przede wszystkim, ścisły
rozdział komentarzy użytkowników zalogowanych i anonimowych, w
praktyce uniemożliwiający dyskusję między jednymi a drugimi. Tutaj
poszukiwania innej biblioteki niestety nie dało rezultatu, trzeba było
dostosować django.contrib.comments.
Drobiazg, ale jak przydatny: slughifi zamienia "zażółć gęślą jaźń"
na "zazolc-gesla-jazn", więc jest wersją funkcji slugify, mądrzejszą o
znajomość wielu znaków narodowych, w tym cyrylicy.
Musiałem też nieco rozbudować własną bibliotekę do obsługi tłumaczeń,
django-multilingual;
eksperymentalne zmiany okazały się bardzo przydatne więc niedługo znajdą
się też w wersji publicznej.
Napisałem też trochę kodu wspomagającego testy modułowe Django,
teraz duża część moich testów wygląda tak:
def test_adding_a_comic(self): self.login() self.get('/') self.click('m-your-account') self.click('publish-now') self.click('cancel') self.assertLocation('/account/ed/') # okay, now go and publish it self.click('publish-now') self.assertContains(self.response, 'name="short_name"') self.assertContains(self.response, 'name="main_language_id"') self.assertContains(self.response, 'name="add" value="save"')
Gdzie 'm-your-account' i 'publish-now' to identyfikatory (nie tekst!)
odsyłaczy na stronie; oczywiście każdy click przechodzi do strony
wskazywanej przez dany odsyłacz. Pozwala to łatwo przetestować całe
sekwencje zdarzeń, i to w sposób niezależny od aktualnie włączonej
wersji językowej interfejsu.
A za miesiąc, wszystko na to wskazuje, coś bardziej skomplikowanego
O autorze: nazywam się Marcin Kaszyński i od ponad 10 lat zajmuję się tworzeniem oprogramowania, od projektowania przez programowanie do zarządzania projektami włącznie. Prowadzę warsztaty Django, będące szybkim i łatwym sposobem na poznanie tego środowiska i rozpoczęcie pracy z pełnym wykorzystaniem jego możliwości.

February 29th, 2008 00:13
[...] tej stronie można przeczytać więcej o WebComicsPot od strony technicznej) February 28, 2008 | In Log [...]
February 29th, 2008 00:23
No i fajnie przeczytać jak to wyglądało z drugiej strony. Gdy dopracujemy workflow… strach się bać