piątek, 25 czerwca 2010

Java 4-ever

Super film ukazujący pokazujący propagandę Microsoftu i alternatywę... ;)



"Hope you're not doing Java and open source...", "They actually enable us to send XML-messages through SOAP! Through SOAP!"
LOL.

A Ty zadajesz sobie to fundamentalne pytanie: "Why do we always use .NET?"

podsumowując .NOT :)

poniedziałek, 21 czerwca 2010

Mocha UI i aplikacja do Geolokalizacji IP

Zainspirowany biblioteką mocha UI napisałem małą aplikacyjkę do geolokalizacji IP z wykorzystaniem google map API.

Zapraszam do oglądania i czekam na komentarze

IP Geolocation Application

Do tej pory nie doceniałem MooTool...

piątek, 7 maja 2010

Ajax w Django. Dajax Project w akcji

Natchnęło mnie kiedyś (już nawet dość dawno) żeby przetestować bibliotekę Dajax do Ajaxa w Django.
Napisałem prostą aplikacyjkę w stylu guestbook.

Potrzebowałem oczywiście dajaxa, którego można sciągnąć ze strony: http://www.dajaxproject.com/
Dajax współpracuje z kilkoma frameworkami JavaScriptowymi, mianowice: jQuery, Prototype, MooTool i Dojo.

No to do dzieła: w settings.py dodajemy wpisy:
DAJAX_JS_FRAMEWORK = "prototype"
DAJAX_MEDIA_PREFIX = "dajax" # http://domain.com/dajax/
DAJAX_CACHE_CONTROL = 10 * 24 * 60 * 60
DAJAX_FUNCTIONS = (
    #Ajax funtions registered to examples.ajax
    'guestbookapp.ajax.pagination',
    'guestbookapp.ajax.send_form',
)

ENTRIES_ON_PAGE = 2
Będę korzystał z prototype, dodatkowo zarejestrowałem dwie funkcje:
send_form - do dodawania nowego wpisu do mojego guestbook'a i pagination do stronicowania wpisów ... ale o nich później.

Teraz ważny trick w urls.py musimy w dodać wpis:
urlpatterns += patterns('',
    ...
    # dajax handler
    (r'^%s/' % settings.DAJAX_MEDIA_PREFIX, include('dajax.urls')),
    ...

To tyle w konfiguracji samego środowiska django. Teraz możemy przejść do tworzenia samej aplikacji, nazwijmy ją guestbook.

plik models.py, chyba niczym tu nie zaskocze - jedna klasa:
from django.db import models

class Entry(models.Model):
    author = models.CharField(u'author', max_length=50)
    email = models.EmailField(blank=True, max_length=50)
    content = models.TextField(u'greeting')
    pub_date = models.DateTimeField(u'added at', db_index=True, auto_now_add=True)
    
    class Meta:
        verbose_name = 'Entry'
        verbose_name_plural = 'Entries'
        ordering = ('-pub_date',)

    def __unicode__(self):
        return self.author

Nie muszę chyba opisywać co zawiera wpis w księdze gości ;)

W zasadzie będziemy mieli tylko jedną stronę, wszystkie requesty będą kierowane przez ajaxa.

Zawartość pliku views.py:
from guestbook.utils import render_response
from django.conf import settings
from django.views.generic import list_detail
from models import Entry
from forms import EntryForm 

def get_pagination_page(page=1):
    from django.core.paginator import Paginator, InvalidPage, EmptyPage
    from django.template.loader import render_to_string
    paginator = Paginator(Entry.objects.all(), 2)
    try:
        page = int(page)
    except ValueError:
        page = 1
    try:
        items = paginator.page(page)
    except (EmptyPage, InvalidPage):
        items = paginator.page(paginator.num_pages)
    return items

def start(request):
    items = get_pagination_page(1)
    context = {
        "form" : EntryForm(),
        "items" : items,
    }
    return render_response(request,'guestbookapp/entry_list.html', context)

Widok start to jedyna strona startowa z formularzem i listą wpisów.

I czas opisać opisać zarejestrowane funkcje (ajax.py):
from django.conf import settings
from dajax.core import Dajax
from models import Entry 

def pagination(request):
    from guestbook.guestbookapp.views import get_pagination_page
    from django.template.loader import render_to_string
    from django.core.paginator import Paginator, InvalidPage, EmptyPage
    try:
        page = int( request.POST['p'] )
    except:
        page = 1
    paginator = Paginator(Entry.objects.all(), settings.ENTRIES_ON_PAGE)
    try:
        items = paginator.page(page)
    except (EmptyPage, InvalidPage):
        items = paginator.page(paginator.num_pages)
    render = render_to_string('guestbookapp/pagination_page.html', { 'items': items })
    dajax = Dajax()
    dajax.assign('#pagination','innerHTML',render)
    return dajax 
 
Paginacja, w zmiennej settings.ENTRIES_ON_PAGE przechowuje liczbę wpisów na stronie

def send_form(request):
    from dajax.utils import deserialize_form
    from forms import EntryForm

    dajax = Dajax()
    form_data = deserialize_form( request.POST.get('form') )
    form = EntryForm(form_data)
    print form
    if form.is_valid():
        from django.core.paginator import Paginator, InvalidPage, EmptyPage
        from django.template.loader import render_to_string
        form.save()
        dajax.removeCSSClass('#add_entry_form input','error')
        form.save()
        #dajax.alert("This form is_valid(), your mail is: %s" % form.cleaned_data.get('email'))
        paginator = Paginator(Entry.objects.all(), settings.ENTRIES_ON_PAGE)
        try:
            items = paginator.page(1)
        except (EmptyPage, InvalidPage):
            items = paginator.page(paginator.num_pages)
        render = render_to_string('guestbookapp/pagination_page.html', { 'items': items })
                
        dajax = Dajax()
        dajax.assign('#pagination','innerHTML',render)
        dajax.assign('#add_form', 'innerHTML', '')
    else:
        dajax.removeCSSClass('#add_entry_form input','error')
        for error in form.errors:
            dajax.addCSSClass('#id_%s' % error,'error')
    return dajax
Wysyłanie formularza ajaxem, w rosponse'ie otrzymujemy informacje o błędach, które są potem podmieniane w widoku.
Zauważcie, że nie musimy bawić się z serializację np. JSONem, wszystko zrobią za nas metody zawarte w dajax.utils odpowiedzialne na przykład za de-serializację formularzy.

Jak to wygląda w akcji?

To tyle, miłej zabawy ajaxem.

sobota, 10 kwietnia 2010

Dlaczego Python? ...po raz drugi

Postaram się przedstawić listę argumentów na korzyść języka Python.

1) Dobre nawyki programistyczne.

Spośród kilku języków (programowania) które znam i z których korzystam na co dzień, właściwie żaden (z wyjątkiem Pythona) nie narzuca dobrego stylu programowania.

Pewnego razu zaglądnąłem do katalogu z programami, które pisałem gdy uczyłem się programować w C

void menu()
{
        char Sciezka[300];  //sciezka pliku
        char wybor;
        int koniec/*konic malej petli*/,Koniec=0;/*koniec duzej petli*/
        int i=0;//pomocniczy licznik 
        
     while(!Koniec)
      {    
           koniec=0;
               printf("Twoj wybor: ");
               scanf("%s",wybor); 
      }
}

int main(int argc, char* argv[])
{   

   
    if(argc != 2){
        printf("**Brak parametrów**\n");
    } else {
         menu();

    return 0; }
}
Pomyślałem sobie: "Jaka masakra". Wyobrażacie sobie znaleźć błąd w takim kodzie?

Gdybym uczył się programować zaczynając od Pythona, pewnie nie zobaczyłbym teraz takiego bajzlu
(pomijając oczywiście wartość merytoryczną tego kodu ;)


Z drugiej jednak strony programując tylko Pythonie, z pominieciem C nie zrozumiesz jak działają wskaźniki,
ręczna alokacja pamięci (malloc, realloc, calloc, itp.) oraz jej zwalnienie. Najpradopodobniej nigdy
nie spotkasz się też z pojęciem wycieku pamięci, buffer overflow czy nie napotkasz na segmentation fault.

2) Zajebiście czytelny kod.

Zazwyczaj gdy patrze na jakiś fragment kodu napisany w języku Python zazwyczaj wiem co on "robi",
gdy zobaczę na odpowiadający mu fragment w innym języku (np. w Javie) musi upłynąć chwilka czasu zanim skumam co autor "miał na myśli" nawet gdy kod jest poprawnie skomentowany. Ponadto prawie zawsze kod w Pythonie będzie zdecydowanie krótszy (no może z wyjątkiem Rubyego, ale ten ma za to kosmiczną składnie ;)

3) Wydajność

"Python is fast enough for our site and allows us to produce
maintainable features in record times, with a minimum of developers,"
powiedział Cuong Do, Software Architect z YouTube.com.

"Python has been an important part of Google since the beginning,
and remains so as the system grows and evolves. Today dozens of Google
engineers use Python, and we're looking for more people with skills in
this language." powiedział Peter Norvig, director of search quality w Google, Inc.

"Python makes us extremely productive, and makes
maintaining a large and rapidly evolving codebase relatively
simple," powiedział Mark Shuttleworth z Thawte Consulting.

Jakieś pytania?

4) Testowanie

Testy jednostkowe są częścią języka od wersji 2.1 wzwyż.
A ich pisanie jest prawdziwą przyjemnością ;), nie to co w Javie... 

5) "Importowanie z przyszłości" :)

"Instrukcja future jest dyrektywą
kompilatora, nakazującą skompilowanie danego modułu z użyciem składni
lub semantyki, która będzie dostępna w określonej przyszłej wersji Pythona"

Fajne, nie ?:) from __future__ import *

6) Przenośność

Kod pythona możesz uruchomić przez interpretator tego języka pod daną platformę lub system,
a w praktyce na Windowsie, Linuxie, Mac'u ...

 Swoją drogą zmuszenie kogoś do pisania w C# jest ograniczaniem jego wolności.
A korzystanie z Mono jest jak murowanie nocnika do podłogi ;).

7) Sam wybierasz paradygmat.

Możesz pisać strukturalnie, obiektowo, a nawet funkcyjnie, nie to co w Javie...
żeby wypisać "hello world" na ekran musisz utworzyć obiekt. 


no i na koniec:
8) Paradoks Pythona wg. Paula Grahama

"[...]Dlatego właśnie, z braku lepszego terminu, nazwę to Paradoksem Pythona: jeśli przedsiębiorstwo decyduje się na napisanie swojego oprogramowania we względnie ezoterycznym języku, będzie mogło zatrudnić lepszych programistów, ponieważ przyciągnie do siebie wyłącznie tych, którzy byli wystarczająco dobrzy, by się tego języka nauczyć. Określenie tej sprzeczności z punktu widzenia programisty jest nawet lepsze: język programowania, którego najlepiej się nauczyć by znaleźć dobrą pracę to język programowania, którego ludzie zwykle nie uczą się po to, by znaleźć pracę."  [1]

Jak na razie tyle, jak mi się jeszcze coś przypomni to dopisze.

[1] polskie tłumaczenie eseju Paula Grahama http://www.pdembinski.konin.lm.pl/python_paradox.html
oryginał: http://www.paulgraham.com/pypar.html

sobota, 13 lutego 2010

Python IDE który wspiera Django :)

Niedawno natknąłem się na bardzo ciekawe IDE dla Pythona, wsparcie dla Django to jedna z jego zalet.


Możliwości: http://code.google.com/p/pyscripter/wiki/Features

piątek, 25 grudnia 2009

Wesołych Świąt

Z okazji świąt przygotowałem ciekawy skrypcik:
                 *                  
                ooo                 
               %oo%*                
              %%*oo*%               
             **ooo%oo*              
            **%%%*o%%o%             
                 %                  
                *%o                 
               %*%%%                
              **oo*o%               
             %%*o*o*%*              
            **%%*o**o%%             
           **o*o%o*%**%*            
          %%*o%%*%***%***           
         %%oo**%**oo%ooo*%          
        *%*%*%*%*oo%*%**%**         
       %ooooo*%%*o*oo*%*%*%%        
      *%oo**o*oo%oo%**ooo%%%%       
                 *                  
                ***                 
               o%o*o                
              %*%oo%*               
             o%*o*%**%              
            %***%oo%o*%             
           *o%o%%%%%%*%*            
          **%*o%%**o*%***           
         %*ooo%o%%o*%%**%%          
        *%%o%o***o%*%%%**o*         
       *****oo*oo*%%%**%%%o%        
      %***o%%**%%%o*oooo%***%       
     %o**o*o%***%%%o%o**%oooo*      
    o%o*o**oo*o%o**o%%%%%o%%**o     
   o*o%o%*%oo%*oo%%o*ooooo%**oo*    
  o*oo*o%%o*ooo%****oo*o%%o%o%*%%   
 *oo*ooo%o**o%**oo*o%%%o%o%oo%o*oo  
o**%ooo%o*o*o*%%o%*%%o%o%%o*oo%**** 

           Wesołych Świąt    


#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import random

def ChristmasTree(levels, n, decoration=["*"]):
    """
    level - liczba poziomów drzewka
    n - wysokość pierwszego poziomu
    decoration - lista ozdób drzewka 
    """
    for j in range(1,levels+1):
        for i in range(j*n):
            line = ""
            for k in range(2*i+1):
                line +=  random.choice(decoration)
            print line.center(2*levels*n)
    print ""
    print u'Wesołych Świąt'.center(2*levels*n) 

ChristmasTree(3, 6, ["*","%","o"])

PS. potrafisz uzyskać podobny efekt w innym języku programowania?
Podejmij wyzwanie :)

środa, 7 października 2009

Wi-Fi router ze starego laptopa

Jestem w posiadaniu starego laptopa Fujitsu Siemens Amilo M7400, który nie ma (już) dysku twardego. Postanowiłem go wykorzystać do stworzenia wi-fi routerka (nie musze kupować access pointa i wykorzystam pozornie bezużytecznego lapka).

System nie może startować z dysku twardego, jedyne możliwości to PXE boot(odpada), live CD(nie będe miał prawa zapisu na nośnik), live USB(!).

Niestety na tym sprzęcie (256Mb RAMu) nie odpale Ubuntu 9.10, nawet Xubuntu też nie wydala.
Znalazłem jednak Lubuntu (dystrybucja ubuntu z lxde,
http://download.lxde.org/lubuntu-9.10/) - wypaliłem na USB(UNetbootin, pisałem o tym w którymś z poprzednich postów) i śmiga:)

Teraz tylko skonfigurować interface'y sieciowe, włączyć routing w kernelu(echo 1 > /proc/sys/net/ipv4/ip_forward) i napisać firewall'a.

Jeszcze ważna uwaga: żeby zadziałała karta sieciowa ipw2200 należy odpalić moduł fsam7400

$sudo modprobe fsam7400 radio=1

Gdyby ktoś potrzebował szyfrowania WPA, to musi sobie skompilać firmware ze źródeł(http://ipw2200.sourceforge.net/ + instrukcja: http://ubuntuforums.org/showthread.php?t=26623), mi WEP całkowice wystarcza(iwconfig $LAN essid [nazwa_sieci] key [s:tekstowy_klucz] channel [nr_kanału] power on).