4 edycja
warsztatów zakończona

Frameworki webowe

Published: Wed 25 February 2015
tags: django flask

Głównym zastosowaniem PHP jest oczywiście web. Nie odkrywam tu żadnej Ameryki, bo sami twórcy już w pierwszym zdaniu na swojej stronie o tym piszą. Najprawdopodobniej i Ty swój pierwszy plik .php testowałeś w przeglądarce. Oczywiście w PHPie można rzeźbić inne “niewebowe” aplikacje, ale programiści je tworzący i tak sporo czasu wcześniej spędzili pisząc stronki małe lub duże.

Jeżeli nasze poprzednie artykuły połechtały Twoją ambicję i na poważnie przymierzasz się do nauki nowego języka, a w przyszłości do zupełnej przesiadki z PHP na Pythona, to pewnie na początek także wybierzesz webówkę. Jest to logiczna decyzja, bo doświadczenie w tworzeniu aplikacji internetowych w PHP pozwoli łatwiej i szybciej zacząć wykonywać podobne zadania w nowym języku.

OK, zacząłeś poznawać Pythona. Czujesz, że nie jest tak źle - w końcu programować potrafisz, a więc jest to kwestia poznania różnic w składni. Ćwiczysz na razie “na sucho”, przerabiając tutoriale albo czytając książki. Z czasów młodości pamiętasz, że pisząc swój pierwszy projekt w PHP nauczyłeś się najwięcej. Po latach, patrząc na ten kod widzisz tysiąc miejsc, które napisałbyś lepiej - to właśnie jest doświadczenie. Podobnie ma chyba każdy programista, bez względu na język. Czas zatem zacząć zbierać doświadczenie w Pythonie, a więc czas na pierwszy projekt w tym języku. Od czego zacząć? Od pomysłu, ale z tym chyba nie będzie problemu, bo pewnie masz ich kilka czekających na trochę wolnego czasu. Co dalej? Wybór frameworka. No i tu zaczynają się schody, bo ekosystem frameworków pythonowych jest dość rozległy i zróżnicowany. W ninejszym artykule postaram się scharakteryzować najpopularniejsze, tak abyś mógł wybrać ten, od którego zaczniesz zdobywanie doświadczenia. Ostrzegam, że jest to porównanie czysto subiektywne, bo wynikające głównie z moich mniej lub bardziej udanych prób użycia w komercyjnych projektach.

Django

Najpopularniejszym frameworkiem pythonowym jest zdecydowanie Django. Jego cechą charakterystyczną jest to, że w jednej paczce znajduje się wszystko potrzebne do zbudowania aplikacji webowej, zarówno małej, jak i takiej z najwyższej półki.

Aplikacje budowane w oparciu o Django opierają się na wzorcu podobnym do MVC, nazywanym MVT (Model-View-Template). Modele definuje się przy użyciu Django ORM i jako storage wykorzystuje się głównie bazy SQL. Django posiada wbudowany panel admina, pozwalający w prosty sposób zarządzać zawartością bazy danych. Panel ten jest przy minimalnej konfiguracji automatycznie generowany na podstawie utworzonych modeli. Widoki mogą być zarówno funkcjami, jak i klasami. Przyporządkowanie widokom URLi odbywa się w jednym miejscu (plik urls.py), dzięki czemu po przejrzeniu tego jednego pliku można dowiedzieć się, jakie URLe są obsługiwane. Szablony tworzy się, używając dość prostego systemu Django Templates. Django chwalony jest za wsparcie dużego community oraz za dobrą dokumentację opisującą całą funkcjonalność frameworka. Dzięki tej dokumentacji oraz temu, że po instalacji dostajemy kompletne środowisko, to próg wejścia jest dość niski. Po przerobieniu oficjalnego tutoriala, będziesz w stanie zrobić większość rzeczy koniecznych do zbudowania aplikacji.

Monolityczność Django niestety ma też swoje wady. Ciężkie, choć nie niemożliwe, staje się zastąpienie któregoś z wbudowanych elementów inną implementacją. Przykładowo, użycie jakiegoś innego ORMa (np. SQLAlchemy) wiąże się z koniecznością porzucenia lub kompletnego przebudowania takich elementów, jak panel admina, autoryzacja, obsługa sesji czy generowanie formularzy. Dzięki temu, że Django jest kompletne, ale mało elastyczne, to nadaje się do standardowych aplikacji (zdecydowana większość projektów), ale gdy potrzebujesz zrealizować jakiś nieszablonowy projekt, to zaczyna się bardziej walka z frameworkiem niż przyjemne programowanie.

class Company(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField(max_length=75, null=True, blank=True)
    website_url = models.URLField(blank=True, null=True)
    city = models.CharField(max_length=100, null=True, blank=True)
    street = models.CharField(max_length=100, null=True, blank=True)
    size = models.IntegerField(null=True, blank=True)
    date_founded = models.CharField(
        help_text='MM/YYYY', null=True, blank=True, max_length=7,
    )

    @property
    def urls(self):
        return {
            'view': reverse('view-company', args=(self.pk,)),
            'edit': reverse('edit-company', args=(self.pk,)),
        }

    def __unicode__(self):
        return self.name

Przykładowy model w Django

Flask

Flask jest zaliczany do mikro-frameworków, to znaczy sam w sobie posiada podstawową funkcjonalność, ale dodatkowo pozwala łatwo ją rozszerzać. Flask zatem jest bardziej klejem, pozwalającym łączyć inne biblioteki ze sobą. I tak na przykład “czysty Flask” nie daje wsparcia dla żadnego storage, ale istneje kilka różnych implementacji, które można doinstalować i zamiennie używać (np. Flask-SQLAlchemy, Flask-MongoAlchemy, Flask-Redis). Podobnie jest z szablonami - podstawowym systemem templatów jest Jinja2, ale można użyć inny zamiennik (np. Mako).

Mottem tego frameworka stało się hasło “one drop at a time” i zgodnie z nim przygotowana jest obszerna dokumentacja. Wiedzę o tym, jak budować aplikację zdobywasz tu porcjami - już po przeczytaniu kilku akapitów jesteś w stanie robić podstawowe rzeczy. Nie potrzebujesz znać bardziej zaawansowanych rzeczy - poznasz je dopiero w momencie, kiedy będziesz ich potrzebował. Dzięki temu nauka idzie całkiem sprawnie i się nie nudzi, a to powoduje, że Flask jest często używany do nauki.

Spora ilość dodatków, którymi można rozszerzyć funkcjonalność Flaska niestety nie jest tak dobrze wspierana, jak sam framework. Dość często zdarza się, że wtyczki nie są już rozwijane lub nie mają aktualnej dokumentacji. W takich sytuacjach niestety trzeba spędzić trochę czasu na googlowaniu zamiennika oferującego podobną funkcjonalność, ale aktywnie wspieranego. Budując swoją aplikację z paczek pochodzących od różnych autorów, trzeba czasem się namęczyć, aby zintegrować je ze sobą. W dokumentacjach wtyczek rzadko znajdziesz gotowe instrukcje jak tego dokonać, ale w takich sytuacjach pomocne jest community i serwisy w stylu Stack Overflow.

@image_view.route(
    '/api/<string:version>/products/<int:prod_id>/images',
    methods=['GET'],
)
@auth_required()
@documented(prod_id="ID of a product")
@output(ProductImagesSeq)
@errors(MissingProduct)
@jsonify
def images_get(version, prod_id):
    """Retrieves a list of product images."""
    return [i.serialize() for i in find_product(prod_id).images]

Przykładowy widok we Flasku

Inne

W świecie frameworków pythonowych znaleźć można dużo więcej ciekawych propozycji. Każdy z tych frameworków kładzie naciska na inną kwestię, był budowany dla nieco innych zadań albo odróżnia się swoją historią. I tak koniecznie trzeba wspomnieć o Pyramid, dla którego bardzo ważną kwestią jest stuprocentowe pokrycie testami oraz prostota budowy bez poświęcania wydajności. Pyramid czerpał inspiracje i doświadczenia z Pylons oraz repoze.bfg - dwóch całkiem niezłych frameworków, które nie są już rozwijane. Zope2 jest jednym z najstarszych frameworków, ale jest ciągle używany głównie jako część składowa CMS o nazwie Plone. Jako następca Zope2 powystał Zope3 (później przemianowany na BlueBream). Framework ten miał pozwalać na prostsze tworzenie dużych aplikacji, jednak nie zdobył on zbyt dużej popularności, głównie z powodu konieczności nauczenia się dość skomplikowanych zagadnień (np. Zope Component Architecture) już na początku nauki.

Warto wspomnieć także o platformie Google App Engine, pozwalającej na uruchamianie aplikacji napisanych między innymi w Pythonie. Platforma ta umożliwia tworzenie aplikacji w dowolnym frameworku kompatybilnym z WSGI. SDK dla App Engine zawiera w sobie prosty framework o nazwie webapp2 i właśnie to podejście jest dość często używane w aplikacjach webowych przystosowanych do tego środowiska.

Kolejną ciekawą propozycją jest Tornado, stworzone przez FriendFeed oraz udostępnione przez Facebooka. W ten framework wbudowano biblioteki wspierające asynchroniczność, dzięki czemu można budować aplikacje z nastawieniem na obsługę wielu jednoczesnych połączeń (np. long pooling, WebSocket). Innymi bibliotekami o podobnym zastosowaniu są Pulsar (async), Twisted (callbacks), Gevent (greenlet). Wymienione wyżej biblioteki pozwalają na budowę dowolnych aplikacji sieciowych (np. gry multiplayer), ale w obsłudze żądań HTTP radzą sobie równie dobrze. Programowanie aplikacji przy użyciu tych frameworków i bibliotek jest trudniejsze i wymaga poznawania trudniejszych zagadnień, a więc polecam je w dalszej części swojej przygody z Pythonem, a nie na początku.

Zakończenie

Mam nadzieję, że ułatwiłem Tobie decyzję, który framework poznać najpierw. A zatem czas na Twój ruch. Przeczytaj i przećwicz tutorial a następnie zabieraj się za swój pierwszy projekt w Pythonie. Powodzenia!

Wojciech Lichota Wojciech Lichota

Wojciech zawodowo programuje w Pythonie od ponad 8 lat, uczestniczył w rozwoju wielu projektów - od prostych stron dla kilku użytkowników, po duże rozwiązania dla międzynarodowych korporacji. W STX Next rozpoczął pracę jako programista, a obecnie jest CTO. Wspiera zespoły w doborze odpowiednich technologii oraz dba o to, aby stosowano dobre praktyki w codziennej pracy.

comments powered by Disqus
Współpraca: programista