Flask/Django: Python RESTful API

Maksimum rezultatów przy minimalnym koszcie

To ideał wszystkich procesów biznesowych, w tym także tworzenia oprogramowania. Jak uzyskać taki efekt dla projektów, które mają napięte terminy oraz wielkie oczekiwania dotyczące wydajności? Niestety nie ma prostej odpowiedzi: jakość oprogramowania wymaga zarówno czasu, jak i pieniędzy, ale… wybór technologii, narzędzi i wzorców może okazać się krytyczny dla cyklu życia produktu. Odpowiednie rozwiązania mogą znacząco poprawić końcowy czas i koszt projektu. Podstawą efektywnego tworzenia oprogramowania jest wnikliwa analiza oraz doświadczenie zbudowane na poprzednich projektach, w tym błędach. Dzisiejszy artykuł poświęcony jest RESTowym API w technologii Python.

Research technologii oraz benchmarki

Wykres poniżej przedstawia wynik benchmarku przeprowadzonego przez TechEmpower (na ich blogu oraz Githubie znajdziecie pełną analizę). Przedstawia on ilość odpowiedzi w formacie JSON, na żądanie HTTP w przeliczeniu na 1 sekundę dla różnych technologii w tym frameworków Pythonowych. Osiągnięto następujące rezultaty dla poszczególnych rozwiązań:

  • Django-stripped (“odchudzone Django” bez context processorów i middlewarów) – 13 269 na sek.
  • Flask – 11 506 na sek.
  • Django – 7122 na sek.

json-i7-latency

Po analizie tego benchmarku można zidentyfikować kilka sposobów, które mogą polepszyć te rezultaty:

  • optymalizacja bazy danych PostgreSQL oparta o użycie PgBouncer i pgPool, która polepszy wyniki mimo braku obsługi problemu connection pool w Django 1.5 lub niżej (dla Django 1.6 zapowiedziano rozwiązanie tego problemu),
  • renderowanie szablonów za pomocą Jinja,
  • użycie ultrajson zamiast biblioteki standardowej do serializacji danych.

Wykres poniżej przedstawia porównanie wydajności bazy PostgreSQL w połączeniu z Django, z wykorzystaniem pgBouncera+pgPoola+Jinja zaprezentowane na blogu AskThePony (tam też znajdziecie dokładne wersje poszczególnych komponentów). Podsumowując zastosowanie tych praktyk może znacząco wpłynąć na wydajność aplikacji.

summary

Zaczynamy!

W wielu przypadkach API jest wąskim gardłem całego systemu informatycznego, bardzo obciążonym komponentem, którego odpowiedzi powinny być szybkie i nie wpływać negatywnie na wrażenia odbioru aplikacji przez użytkownika. Poniżej zaprezentowane zostanie porównanie wad i zalet wybranych technologii RESTowych, ale najpierw kod źródłowy przedstawiający implementację przykładowego WebService’u.

Flask

1. Implementacja modelu Member w oparciu o SQLAlchemy:

2. Metoda obsługująca żądania dla API:

Klasa MethodView rozpoznaje poszczególne typy RESTowych żądań w oparciu o generyczną metodę dispatch. I API jest gotowe. To było bardzo szybkie, ale możemy jeszcze ten kod tuningować.

3. Poniższy kod to 18 linii, w tym 4 linie konfiguracji, 2 linie implementacji API. Ten krótki skrypt stanowi całą aplikację tworzącą proste API dla modelu Member, a rezultat jest identyczny jak w przykładzie powyżej:

Biblioteka RESTless

Powyższy skrypt był fajny, ale jak Flask będzie działał na produkcji z realnym projektem, konkretnymi wymaganiami i tam gdzie rozwój oprogramowania jest dyktowany przez konkretne potrzeby klienta?

Biblioteka RESTless dla Flaska pozwala w łatwy sposób dodać wiele użytecznych funkcjonalności:

1. Wersjonowanie:

2. Walidacja:

Przykładowy rezultat:
{ "validation_errors": {"email": "Email is not valid.."}}

3. Doprecyzowanie jakie konkretnie dane mają być udostępnione za pośrednictwem API:

4. Paginacja wyników:

5. Pre i post processory:

6. Autentykacja:

7. Filtrowanie:

Podsumowując, używanie mikroframeworka takiego jak Flask razem z biblioteką RESTless jest dobrym rozwiązaniem, szczególnie gdy API dodaje się do już istniejących aplikacji.

Zalety Flaska:

  • bardzo dobra wydajność,
  • szybkie i proste prototypowanie API,
  • prosty i szybki do nauczenia nawet dla osób, które wcześniej nie miały styczności z Flaskiem,
  • może działać w oparciu o Gunicorna (Django i Flask mogą, więc działać razem na jednym serwerze),
  • domyślnie korzysta z ORMa SQLAlchemy, który daje większe możliwości niż Django ORM.

Wady tego rozwiązania:

  • rozproszona dokumentacja, ponieważ Flask ma bardzo wiele dodatków,
  • trzeba włożyć więcej wysiłku w stworzenie logicznej struktury aplikacji,
  • brak możliwości używania metod pomocnicznych znajdujących się w Django oraz własnych bibliotek do obsługi logiki aplikacji.

A co z rozwiązaniami RESTowymi dostępnymi dla Django?

Jest wiele dostępnych bibliotek do obługi RESTa dla Django: django-rest-framework, django-tastypie, django-piston (martyw projekt), itd. W tym artykule zostanie przedstawiony tylko django-rest-framework, ponieważ zbudowany jest na dobrych wzorcach, jest dynamicznie rozwijany i utrzymywany, ma szybki support oraz szczegółową i aktualną dokumentację.

Na początku warto zasygnalizować, że nazwa django-rest-frameworka została wybrana ze względu na możliwość szybkiego i łatwego znalezienia go przez programistów. Ale niestety nie jest to poprawna terminologia. Biblioteka ta bazuje na szerszym koncepcie niż REST, a konkretnie na idei Hypermedia driven APIs. Tutaj pominę już samą definicję, natomiast więcej znajdziecie tutaj.

Django-rest-framework jest bardzo zaawansowanym narzędziem, natomiast poniżej przedstawiona jest tylko najbardziej podstawowa realizacja WebServicu:

1. Definicja modelu danych:

2. Implementacja serializera – klasy opisującej jak powinna wyglądać reprezentacja modelu w samym API:

3. Widok:

4. URL:

Zaletami tego rozwiązania są:

  • bardziej zaawansowane i rozszerzalne narzędzie niż w przypadku Flaska,
  • implementacja dopasowana do potrzeb, jest wiele dróg do implementacji tego samego rezultatu,
  • możliwość korzystania z klas i metod zaimplementowanych w Django oraz własnego kodu,
  • szybki do automatycznego testowania (w oparciu o Django TestCase).

Wady:

  • słabe wsparcie obiektów zagnieżdżonych, w konsekwencji bardziej czasochłonne jest zintegrowanie np. z RestKitem – biblioteką pomocniczą do obsługi RESTa na platformie iOS,
  • mniejsza wydajność niż w przypadku Flaska (ale jest światełko w tunelu: na blogu Dabaapps można znależć porady jak profilować django-rest-framework, aby uzyskać lepsze rezultaty).

Podsumowanie

Tworzenie API, dzięki zastosowanym rozwiązaniom może być naprawdę szybkie, proste i przynieść wiele korzyści projektowi. Osobiście w oparciu o moje doświadczenia jednak wolę używać django-rest-framework z powodu przyjemniejszej współpracy z samą aplikacją Django. Struktura aplikacji odpowiedzialnej za API jest bardziej logiczna, bo wymuszona wzorcami Django. W łatwy sposób można ją także testować co ma ogromne znaczenie dla rozwoju i utrzymania projektu. Ale Flask także jest dobrym rozwiązaniem, szczególnie gdy API ma być mocno obciążone.

Współzałożycielka Solution4Future. Od kilku lat programuje w technologii Python/Django oraz JavaScript. Swoje kompetencje zawodowe poszerza o wiedzę i umiejętności z zakresu tworzenia oprogramowania na platformy mobilne między innymi na iOS i Android. Popularyzuje ideę Open Source i od zawsze korzysta z Linuxa. Po pracy podróżuje i wędruje po górach, posiada artystyczną duszę, maluje i fotografuje.

  • sznapka

    Używałem Flask do prostych pierdółek, ale widzę, że nadaje się też do poważnych rzeczy 🙂

  • Łukasz Szymański

    Rzeczowy i przydatny artykuł. Oby takich więcej. Brawo.

  • Aleksander Cynarski

    Fajny ten ultrajson, dzieki 🙂

  • Jacek Jackowiak

    A jak wygląda w Django wsparcie dla HATEOAS’u? Po stronie Javy próbowałem trochę pomęczyć się nad automatycznym generowaniem automatycznej relacji pomiędzy zasobami (zgodne z HAL), ale było z tym wtedy trochę problemów niestety.

Send this to a friend

webmastah.weekly
Cotygodniowa porcja linków ze świata WEBDEV BEZ spamu, TYLKO samo mięcho!
Zobacz poprzednie wydania. Dołącz do 2 tysięcy webdeveloperów!
HTML5, CSS3, JS (React, Angular, Ember, Vue), PHP, SQL