Chętnie spotkałbym się z tymi programistami Delphi, którzy robią (zawodowo lub OMC zawodowo) w Pythonie. Właśnie nie dawno zobaczyłem posta Fiedzi na django-users, parę innych nazwisk też mi się wydaje znajomych...
Markdown to fajny wynalazek, ale zaskakująco niebezpieczny i to w miejscu, którego zwykle się nie spodziewamy... Wspomniał o tym jakiś czas temu Jeff Atwood przy okazji jakichś innych wynurzeń. Utkwiło mi to bardzo mocno w pamięci, pewnie dlatego, że kiedyś zdarzyło mi się popełnić aplikację podatną na XSS. Tak, nieumiejętnie (nazwałbym to bezmyślnie, ale nie jest moim zamiarem itd.) zastosowany markdown wystawi na niebezpieczeństwo także i Twój serwis. Zastanawiam się nad tym, jak zastosować do zmyślnie, bo chciałbym użytkownikom wMiastoWzięci.pl dać do ręki coś, co im się przyda, a jednocześnie nie pozwoli im na wyrządzenie żadnych szkód (obojętne, umyślnie czy nieumyślnie).
Pewnym rozwiązaniem mogłoby być oczyszczenie tekstu źródłowego przed zapuszczeniem na nim filtra markdown — ale to trochę przypomina wylewanie dziecka z kąpielą, bo wyłącza część użyteczności markdown. Z drugiej jednak strony, rozwiązanie Jeffa A. (czyszczenie tylko części HTML) nie wydaje mi się rozsądne, przede wszystkim z powodu ogromnego skomplikowania zagadnienia. Czyżby była to sytuacja bez wyjścia?
Dlaczego właśnie Python? Często sam zadaję sobie to pytanie i próbuję dać autorytatywną odpowiedź, biorąc pod uwagę mnogość języków, które znam i których używałem (zawodowo i hobbistycznie) w ciągu moich ponad 10 lat praktyki. W ostatnich dniach pojawiło się kilka głosów, które dają pewne sugestie co do możliwej odpowiedzi:
Jestem coraz bliżej odpowiedzi na moje pytanie.
Dziś o 8 rano w ośrodku na Radarowej zdałem egzamin teoretyczny na prawo jazdy B. Ciąg dalszy 2 grudnia o 19, także na Radarowej — będę zdawał egzamin praktyczny. Mam nadzieję, że strategia Bernarda Montgomery da mi równie dobre wyniki, jak dawała jemu: tylko miażdżąca przewaga jest przewagą wystarczającą.
Zdarzyło się tak, że zrobiłem literówkę w urlconfie i stało się, Google zaindeksowało mi stronę pod błędnym url-em. O ja nieszczęsna, ale przecież zdarza się w najlepszej rodzinie. Trzeba było zmontować jakiegoś redirecta. Co prawda Django ma jakąś swoją aplikację do redirectów (django.contrib.redirects), ale przecież nie o to chodzi, żeby Django robiło wszystko, skoro to taka drobnostka — przecież każdy serwer http ma coś do robienia redirectów, Lighttpd nie jest żadnym wyjątkiem. Trochę nad tym posiedziałem (bo orłem z wyrażeń regularnych to ja nie jestem...) i działa jak złoto:
$HTTP["host"] =~ "(^|\.)wmiastowzieci\.pl$" {
url.redirect = (
"/miajsca/$" => "/miejsca/",
)
}
Żeby było ciekawiej (choć to babol i w nowszym lighty będzie zmienione), lighty w tym momencie wysyła 301 (czyli permanent redirect) co akurat w moim przypadku robi dobrze, bo nie zamierzam więcej popełniać tej literówki. :)
To uczucie nieporównywalne z niczym: budujesz aplikację przez kilka tygodni lub miesięcu i przez cały czas zastanawiasz się czy ktoś będzie tego używał?. W takiej niepewności trwasz dopóki nie zauważysz, że jednak ktoś zdecydował się jej użyć, a wtedy... No i wtedy właśnie przychodzi ten strzał adrenaliny, który mogę porównać tylko z paroma rzeczami (niestety, nie mogę napisać, co to za rzeczy, bo każda z nich jest albo szkodliwa albo zakazana przez prawo — tę stronę przecież czytują dzieci...). Dziś rano spojrzałem w panel administracyjny jednego z moich prywatnych serwisów i poczułem właśnie TO.
Pomimo trzymania aplikacji w niemal całkowitej tajemnicy do czasu ukończenia prac (wiedziała o niej tylko moja żona i Google, o ile ktoś wiedział czego ma szukać), ktoś zajrzał na wMiastoWzięci.pl i dodał wydarzenie (choćby z tego powodu warte uwiecznienia). Nie będę tego ukrywał dłużej, to mój serwis. Wciąż jeszcze jest szlifowany, wciąż nie wszystko w nim działa, ale jak widać komuś to nie przeszkadzało. Co nie działa:
-
zgłaszanie obiektów (wydarzenia, zdjęcia, recenzje) do moderacji
-
komentarze do wydarzeń i miejsc
-
przeglądanie wielu etykiet na raz
Dla spragnionych informacji technicznych: serwis działa na Django-trunk, baza to MySQL 5.0 (z backendem MyISAM), deployment na FastCGI/lighttpd.
A skoro już poszło w świat, to skończył się luźny czas developmentu w modelu langsam, langsam i trzeba w szybkim tempie dorobić brakujące funkcje serwisu. ;)
Turbo Pascal jest dziś starszy, niż spora część programistycznego światka. Wspominam go z sentymentem, bo to był mój pierwszy język programowania, w który wsiąkłem na dobre (i na wiele lat). Nauczyłem się przy jego użyciu (a potem Delphi, poczynając od wersji 2) wielu rzeczy, na nim wyrosłem na dojrzałego programistę i w nim napisałem moje pierwsze aplikacje, używane przez innych ludzi. Na dobre skończyłem pisać w Delphi/Pascalu dopiero z końcem 2006 roku, więc pamięć jest jeszcze żywa.
Jak się ma 25 lat, to już można sobie golnąć. Zdrowie młodzieńca!
Pomimo tego, że robię w Django od paru lat, wciąż zdarzają mi się odkrycia na miarę archimedejskiej eureki. Dziś właśnie zauważyłem, że skrót render_to_response może przyjmować jako pierwszy argument nie tylko nazwę szablonu, ale także listę nazw szablonów. Dzięki temu wiekopomnemu odkryciu kod, który wyglądał dość marnie:
templates = [
'flagging/%s_flagging_form.html' % obj._meta.module_name,
'flagging/flagging_form.html',
]
template = loader.select_template(templates)
return HttpResponse(template.render(ctx))
teraz może wyglądać trochę ładniej:
templates = [
'flagging/%s_flagging_form.html' % obj._meta.module_name,
'flagging/flagging_form.html',
]
return render_to_response(templates, ctx)
Świadomie używam określeń ładnie i brzydko, bo chodzi tu jedynie o estetykę (obydwa warianty robią dokładnie to samo pod spodem).
Na swoje usprawiedliwienie mogę powiedzieć tylko tyle, że takie zachowanie render_to_response jest obecnie nieudokumentowane (ale zgłosiłem odpowiedniego patcha).
I'm pleased to announce my first (hopefully) reusable app for Django: django-confirmation. The idea for this app came from my personal need to handle confirming object's creation on one of my sites. I found few apps performing similar tasks, but both are targeting single classes of objects, while I needed more generic approach (I hate this word...) — there are several classes of objects that need to be confirmed separately but using the same mechanism.
The use case for this app is as follows:
-
non-registered/not-logged-in user creates an object;
-
application sends an email asking user to click (within configurable period of time) on provided link to make the object "active";
-
user clicks a link and makes the object "active" or
-
key expires after specified amount of time.
The implementation is based on what I found in other apps, specially django-registration and django-email-confirmation, but with added support for confirming generic Django model instances (as long as they can have different activity states, that is).
Django jest fantastyczne m.in. w tym, że istnieje masa podłączalnych aplikacji, które w sposób wystarczająco generyczny realizują często spotykane zadania, jak np. django-registration do rejestrowania użytkowników, czy django-tagging do etykietowania obiektów. Część z tych aplikacji jest naprawdę wysokiej jakości, w dodatku łatwo konfigurowalnych i możliwych do dopasowania w dość szerokim zakresie. Są jednak takie, które dobrze się zapowiadają od dłuższego czasu, jednak na tym się kończy. Co bardziej zaskakujące, wszystkie te potencjalnie użyteczne aplikacje pochodzą z projektu Pinax.
W jednym z projektów potrzebuję dodać funkcję powiadamiania użytkowników o wystąpieniu pewnych zdarzeń. Jest aplikacja django-notification, ale w stanie obecnym nie nadaje się do wykorzystania poza Pinaxem (lub w sposób jakkolwiek różny od tego, jak to jest robione w Pinaksie). Zgłoszone są problemy z tym związane, jednak zostały odłożone na lepsze czasy. Będę musiał wziąć kod django-notification i wzorując się na nim napisać swoją własną aplikacyjkę, bo na te lepsze czasy się nie doczekam.
Inny przykład. Niedawno potrzebowałem dodać do pewnego projektu możliwość tworzenia obiektów przez niezalogowanych użytkowników — wymagane jest wtedy podanie adresu email i potwierdzenie dodania obiektu przez standardowe kliknięcie w przesłany link. Znalazłem aplikację django-email-confirmation, która robi coś podobnego, ale nie nadaje się do potwierdzania jakichkolwiek innych obiektów, niż jej własne (a ja potrzebowałem zastosować ten mechanizm do 3-4 różnych klas obiektów). Trzeba było napisać własną, na szczęście okazało się to dość proste, przyjmując django-email-confirmation za wzór.
I to samo mam za każdym razem, gdy trafiam na aplikację, która mogłaby mi się przydać, a pochodzi z Pinaxa — bez zakodowania własnego rozwiązania bazującego na tym kodzie się nie obejdzie. Rozumiem, że Pinax jest rozwijany w normalny dla OS/FS sposób, to znaczy w czasie wolnym i nikt nie bierze za to pieniędzy, ale skoro tak to wygląda, to jaki jest sens wydzielać aplikacje jako niby reużywalne, skoro tak naprawdę nie dają się użyć nigdzie poza aplikacjami typu Pinaxa i ich reużywalność to głęboki mit?
Gra, która zostanie ożywiona (stąd "Revival", i trochę z mojego upodobania do pewnego utworu The Soulsavers), to Gwiezdny Kupiec, wydany dawno temu przez nieistniejącą już firmę Encore. Ktoś kiedyś zrobił wersję interwebową tej gry, ale serwis już dawno zniknął z sieci — gdyby nie ten fakt nawet nie próbowałbym myśleć o odtworzeniu tej gry. Gratuluję wszystkim, którzy odgadli, a tych, co nie odgadli pocieszam, że to dość niszowe zagadnienie. ;)
Co do współpracy... Kilka osób się odezwało, dziękuję za zainteresowanie. Wybrańcem losu został Franek Goliński, który użył jokera, bo pracuje ze mną i mamy bezpośredni kontakt przez 8 godzin dziennie (siedzimy może 3 metry od siebie...).
Szczerze mówiąc, nie spodziewałem się w ogóle odzewu, a tu proszę... Zaskoczenie.
Poszukuję współpracownika do odtworzenia pewnej kultowej gry planszowej w realiach interwebu (Django 1.x + jQuery), może być na AppEngine, ale nie musi. Projekt może być Open Source, ale nie musi (bo w sumie kogo to obchodzi...). Wskazany wiek > 30 lat (młodsi raczej nie będą mieli odpowiedniego szacunku dla tej gry ;)). Gra jest turową strategią, więc łatwo nie będzie.
Kontakt tam gdzie zawsze - Jarek kropka Zgoda na usłudze pocztowej Google®. Proszę, tylko poważne propozycje...
[edit]: kilka osób mnie już o to pytało, nie chodzi o grę Revival (nawet nie wiem, co to takiego).
...a koniec może być nawet żałosny, byle tylko był szybki.
22 listopada 2008 roku w ośrodku na Radarowej zaczynam moją odyseję egzaminacyjną na prawo jazdy kat. B. B, czyli będę zdawał aż do skutku.
Z ogromną przykrością i z prawdziwym żalem odkryłem, że Hacknot.info (nie linkuję, bo domenę przejęli już squatterzy) jeden z najciekawszych serwisów z esejami dotyczącymi produkcji oprogramowania zniknął z sieci. Zniknęła masa fantastycznych artukułów (często bardzo kontrowersyjnych, ale zawsze ciekawych i pozwalających przemyśleć poważnie różne sprawy). Pozostała książka (do ściągnięcia za darmo w postaci PDF lub do kupienia za parę €), ale zawiera ona tylko wybór esejów Eda Johnsona.
Szkoda, naprawdę wielka szkoda. Z drugiej strony, nie mogę uwierzyć w to, że cała zawartość tego serwisu zniknęła bez śladu (przecież była na CC!), więc przez cały czas można mieć jakąś nadzieję, że gdzieś uchowała się lokalna kopia...