Tworzenie bazodanowych aplikacji desktopowych za pomocą frameworka Camelot

Camelot to framework do szybkiego tworzenia aplikacji desktopowych w oparciu o Pythona, Qt4 i SQLAlchemy. Framework ten celuje w aplikacje oparte o bazy danych - tam gdzie mamy kolekcje danych i chcemy nimi zarządzać (katalogi, zbiory różnych danych). Poważną konkurencją dla tego typu aplikacji desktopowych są aplikacje webowe, które dość często mogą okazać się prostsze lub tańsze do wykonania. W porównaniu do czystego PyQt4 framework daje nam gotowy szkielet oraz interfejs dla całej aplikacji (który dalej można rozszerzać i modyfikować). Oto jedna z prezentacji Camelota:

Instalacja Python-Camelot

Instalacja jest standardowa, wystarczy użyć pip:
pip install camelot
Framework ma wiele zależności:
  • Qt4
  • PyQt
  • SQLAlchemy
  • Elixir
  • sqlalchemy-migrate
  • Jinja2
  • chardet
  • xlwt
  • xlrd
Pakiety Qt4 jak i PyQt4 warto zainstalować z repozytorium dystrybucji. Reszta powinna zostać rozwiązana przez pip (ew. zainstaluj camelot z flagą --upgrade by zaktualizować stare wersje). Po zainstalowaniu frameworka możemy stworzyć pierwszą aplikację.

Podstawowe elementy aplikacji

By stworzyć nową aplikację tworzymy pusty katalog i w nim wykonujemy polecenie:
python -m camelot.bin.camelot_admin
Pojawi się okno dialogowe, w którym będziemy mogli podać podstawowe dane naszej aplikacji:
Okno dialogowe nowej aplikacji Camelot

Najważniejsza dla programisty jest nazwa modułu. W tym przypadku jest to "videostore". Po stworzeniu aplikacji w katalogu pojawi się parę plików i katalog o nazwie takiej jak nazwa modułu.

By uruchomić aplikację wystarczy wykonać:
python main.py
Pierwsze uruchomienie może trwać nawet i kilkanaście sekund - trzeba czekać aż pojawi się lewa belka nawigacyjna:
Główne okno aplikacji Camelot

Lewa belka nawigacyjna zawiera w zakładkach "encje" przedstawiające tabele w bazie danych. Domyślnie mamy dwie - "Persons" i "Organisations". Każda zakładka jest sekcją.

Gdy z sekcji "relation" wybierzemy encję "Person" to pojawi nam się lista osób - lista rekordów zapisanych w tej tabeli. Na początku nie będzie żadnego. Możemy dodać nowe korzystając z górnego menu, które pojawia się wraz z wyborem encji:

Zarządzanie wpisami w encji Person
Dodawanie nowego wpisu
Lista osób z nowo dodanym rekordem
Gdy wypełniliśmy formularz i chcemy zapisać-dodać nowy wpis po prostu zamykamy okno z formularzem (trochę nietypowe). Tak wygląda Camelot w najprostszej postaci - taka nakładka na bazę danych - choć na tym możliwości tego frameworka się nie kończą.

Własne modele

Teraz przejdę przez proces tworzenia i konfiguracji modelu oraz sekcji. Tworząc aplikację będziemy musieli zdefiniować jakieś modele opisujące tabele w bazie danych.

Na początek można zajrzeć do settings.py, tam mamy zdefiniowane dane do bazy danych (create_engine). Domyślnie będzie to SQLite. Camelot używa SQLAlchemy do obsługi baz danych (i ew. nieco Elixira w modelach). Na potrzeby pierwszych testów nie trzeba nic tu zmieniać.

W katalogu videostore (nazwa naszego modułu) znajdziemy kilka ważnych plików. Pierwszy to model.py - zawiera on definicje naszych modeli. Drugi application_admin.py zawiera konfigurację sekcji - ile ich jest i jakie tabele (modele) zawierają.

Stwórzmy więc pierwszy model. Do models.py dodaj taki oto kod:
from sqlalchemy import Unicode, Date
from elixir import Entity, Field, using_options
from camelot.admin.entity_admin import EntityAdmin

class Movie(Entity):
  using_options(tablename='movie')

  title = Field(Unicode(60), required=True)
  short_description = Field(Unicode(512))
  release_date = Field(Date)
  genre = Field(Unicode(15))

  class Admin(EntityAdmin):
    verbose_name = 'Movie'
    list_display = ['title', 'short_description', 'release_date', 'genre']

  def __unicode__(self):
    return self.title or 'untitled movie'

Mamy tutaj typowy model zdefiniowany za pomocą nakładki Elixir. Na początek określam własną nazwę dla tabeli, a następnie definiuję kolumny - tytuł, krótki opis, data premiery i kategorię filmu. Ten model definiuje samą tabelę. Czymś "nowym" jest klasa Admin (EntityAdmin) definiującej co i jak ma być wyświetlane w aplikacji. "verbose_name" określa nazwę encji wyświetlaną w aplikacji. "list_display" określa które kolumny mają być wyświetlane na liście wpisów. Zasady bardzo podobne do webowych frameworków (jak np. Django).

Teraz musimy umieścić nasz model w jakiejś sekcji. application_admin.py przechowuje listę sekcji i modele do nich przypisane. Oto zmodyfikowana lista sekcji zawierająca nową sekcję "Movies", a w niej nasz nowy model "Movie":

class MyApplicationAdmin(ApplicationAdmin):
  
    name = 'Videostore'
    application_url = 'http://www.python-camelot.com'
    help_url = 'http://www.python-camelot.com/docs.html'
    author = 'My Company'
    domain = 'mydomain.com'
    
    def get_sections(self):
        from camelot.model.memento import Memento
        from camelot.model.authentication import Person, Organization[rk:thumb src="python/camelot4b.png" alt="Dodawanie nowego wpisu"]
        from camelot.model.i18n import Translation
        # import model
        from model import Movie
        return [ Section( 'relation',
                          self,
                          Icon('tango/22x22/apps/system-users.png'),
                          items = [Person, Organization]),
                 Section( 'configuration',
                          self,
                          Icon('tango/22x22/categories/preferences-system.png'),
                          items = [Memento, Translation]),
                # our new section
                Section('Movies',
			  self,
			  Icon('tango/22x22/mimetypes/video-x-generic.png'),
			  items = [Movie])
                ]
Tango zawiera zestaw ikon Tango, które można wykorzystywać w definicjach m.in. sekcji. Oczywiście można też użyć własnych ikon dołączonych do aplikacji. Gdy teraz uruchomimy aplikację powinniśmy zobaczyć naszą sekcję i model:
Własny model w aplikacji Camelot

Kolejnym ważnym elementem jest obsługa relacji między tabelami. SQLAlchemy, Elixir i Camelot je obsługują. Kasujemy plik bazy danych - model-data.sqlite i zmieniamy modele.

By stworzyć relację wystarczy użyć pól typu ManyToOne i OneToMany oferowany przez Elixira. Dla przykładu dodajmy model "Director" przechowujący reżyserów filmów:

from camelot.model import metadata

__metadata__ = metadata


from sqlalchemy import Unicode, Date
from elixir import Entity, Field, using_options
from camelot.admin.entity_admin import EntityAdmin
from elixir import ManyToOne, OneToMany

class Director(Entity):
  using_options(tablename='director')

  name = Field(Unicode(60))
  movies = OneToMany('Movie')
  
  class Admin(EntityAdmin):
    verbose_name = 'Director'
    list_display = ['name']

  def __unicode__(self):
    return self.name or 'unknown director'

class Movie(Entity):
  using_options(tablename='movie')
  title = Field(Unicode(60), required=True)
  short_description = Field(Unicode(512))
  release_date = Field(Date)
  genre = Field(Unicode(15))
  director = ManyToOne('Director')
  
  class Admin(EntityAdmin):
    verbose_name = 'Movie'
    list_display = ['title', 'short_description', 'release_date', 'genre', 'director']

  def __unicode__(self):
    return self.title or 'untitled movie'
Model "Director" ma relację jeden do wielu do modelu "Movie" - reżyser może reżyserować wiele filmów. Na odwrót mamy w modelu "Movie" - relację wiele do jednego. Po uruchomieniu aplikacji stworzone zostaną nowe tabele. Gdy będziemy chcieli dodać film pojawi się w formularzu pole na reżysera - można wybrać istniejącego lub dodać nowego:
Dodawanie nowego filmu z polem relacji do modelu reżysera
Tak oto wygląda tworzenie prostej aplikacji w Camelocie. Na stronie projektu jest dostępnych kilka prezentacji przedstawiających bardziej złożone funkcjonalności.
RkBlog

PyQt, 10 April 2012

Comment article
Comment article RkBlog main page Search RSS Contact