admin 0Comment

Pamiętam moje absolutne początki, jeśli chodzi o samodzielną naukę programowania i towarzyszącą temu dezorientację związaną z programistycznym słownictwem. Przyznacie, że jest tego trochę – często wyzwaniem jest już samo zorientowanie się, o czym w ogóle w danym momencie czytamy lub słuchamy. Jednym z określeń, które napotkałem wtedy to tzw. CRUD. Jest to akronim, którego rozwinięciem są słowa create, read, update and delete (pol. utwórz, odczytaj, aktualizuj i usuń). Określa on cztery podstawowe funkcje, implementowane w programach, które korzystają z pamięci trwałej i umożliwiają zarządzanie nią. Niezależnie od tego, jakimi obiektami operuje twoja aplikacja, w pewnym momencie będzie najprawdopodobniej musiała korzystać z każdej z tych funkcji. Nic dziwnego więc, że implementacja tych funkcjonalności jest jedną z pierwszych rzeczy, jakie chcę zrobić przy okazji mojego konkursowego pomysłu.

Zanim jednak o tym, warto żebym wyjaśnił wam, jakie dane będę musiał zapisywać. Więcej o mojej web aplikacji napisałem w tym tekście, nie ma więc sensu żebym się tutaj powtarzał. Przypomnę tylko krótko, że bazą dla niej jest prosta aplikacja TUI (Text User Interface), pozwalająca zapisywać comiesięczny budżet, przeglądać dane oraz wykonywać jego podstawową analizę. Aktualny kod aplikacji możecie podejrzeć na moim koncie GitHub.

Skoro więc sednem mojego programu jest kolekcjonowanie danych dotyczących sum w określonym czasie, muszę ująć je w jakiś model lub modele, i zaimplementować opisywane na początku tego tekstu funkcjonalności. Już na etapie planowania projektu miałem kilka pomysłów, w jaki sposób rozwiązać tę kwestię. Czy np. tworzyć dodatkowe obiekty, które umożliwiały by kolekcjonowanie obiektów głównych (o tych za chwilkę) zależnie od tego, dla jakiego okresu gromadzą dane? Na tę chwilę (oczywiście może się to zmienić w trakcie prac nad projektem) zdecydowałem się na ujęcie najprostsze – sednem mojej aplikacji są obiekty (iteracje modelu) klasy Stash, zawierające m. in. takie dane jak amount – suma czy też date-data, moment w czasie, dla którego obiekt został stworzony. Oto kod modelu:

class Stash(models.Model):
    NAME_CHOICES = (
        ('Bank account', 'bank acc'),
        ('Savings', 'savings'),
        ('Wallet', 'wallet'),
        ('Others', 'others'),
    )
    user = models.ForeignKey(User)
    name = models.CharField(max_length=20, choices=NAME_CHOICES)
    date = models.DateField()
    amount = models.FloatField()

Oprócz opisanych powyżej, w modelu określiłem także name – nazwę, korzystającą z domyślnego zbioru (w przyszłości mam zamiar dać użytkownikowi możliwość jego personalizacji) o nazwie NAME_CHOICES  a także przyporządkowanie każdego obiektu do konkretnego użytkownika.

Jeśli zajrzeliście do kodu aplikacji TUI, będącej bazą dla tego projektu, wiecie, że tam stosowałem także obiekty klas Year oraz Month, umożliwiające mi wygodniejsze zarządzanie obiektami klasy Stash. W przypadku aplikacji webowej zrezygnowałem (przynajmniej w tej jej wersji) z tego rozwiązania, ponieważ Django zapewnia bardzo fajną obsługę zapytań na bazę danych, w tym bazując na danych typu Date czy DateTime. Z tej perspektywy wydaje mi się, że stosowanie dodatkowych klas tylko po to, by umieszczać konkretne obiekty Stash w czasie, byłoby przykładem tzw. over-engineering czyli mówiąc wprost – przekombinowałbym ;). Czy mam rację? Czas pokaże.

Wracamy jednak do funkcjonalności CRUD. Zacząłem od zaimplementowania funkcji create. Chciałem by użytkownik mógł od razu, za jednym razem stworzyć kilka iteracji obiektów Stash, jednocześnie jednak warto by ich domyślne nazwy były już wyświetlone a także by data dla tego zbioru obiektów była wpisywana tylko raz. Przyznaję, że trochę mi to zajęło – dopiero niedawno zagłębiłem się w Django i wciąż jestem na zdecydowanie początkowym poziomie, ale dzięki temu każdy tego rodzaju problem bardzo mnie rozwija. Nie będę tutaj wrzucał całości kodu, skoro możecie spojrzeć na niego na moim koncie GitHub, napiszę tylko, że ostatecznie skorzystałem z takich rozwiązań jak osobny form dla daty, formset dla obiektów Stash, który posiadał initial values w zakresie nazw konkretnych iteracji. Całość (tylko z bardzo podstawowym front-endem, na którego rozwinięcie przyjdzie czas później) pobiera dane w ten sposób:

Tak więc można powiedzieć, że literka C z CRUDa jest już wstępnie ogarnięta :).

Kolejne z podstawowych funkcjonalności nie są już tak wyraźnie odseparowane od siebie nawzajem. Początkowo stworzyłem funkcję wyświetlania danych (w dwóch opcjach – wyświetlenia całości danych dla użytkownika oraz drugą, pozwalającą mu wybrać czasowy zakres między datami, i wyświetlającą wtedy dane umieszczone w tym przedziale) ale pomyślałem, że skoro już użytkownik wyświetla obiekty klasy Stash, to może warto od razu dać mu opcję ich edycji lub nawet kasowania? Rezultatem jest takie działanie, dla opcji wyświetlenia wszystkich danych dla danego użytkownika, wraz z przykładowymi danymi:

Aby uzyskać podobny wynik, ale zawężając wcześniej zakres danych, użytkownik musi skorzystać z takiego formularza:

W tym momencie można powiedzieć podstawowe funkcjonalności są już zaimplementowane, ale brakuje m. in. wygodnego sposobu usuwania większej ilości danych na raz – co, jeśli użytkownik będzie chciał wykasować dane dla całego roku? Klikanie kilkudziesięciu przycisków delete niekoniecznie jest najsensowniejszym rozwiązaniem, mogę więc poszerzyć funkcjonalność Delete o widok kasujący większą ilość danych na raz. Mogę nawet skorzystać z powyższego szablonu (jeśli potraktujemy tekst widoczny poniżej informacji logowania jako zmienną) bo po co niepotrzebnie mnożyć byty :):

Mamy więc możliwość usunięcia większej ilości danych na raz. Na tę chwilę zamyka to implementację podstawowych funkcjonalności CRUD w moim projekcie ale już mam kilka uwag i pomysłów, które pojawiły się na bieżąco, co i jak powinienem tutaj zmienić lub rozszerzyć. Nie chcę jednak zakopać się w jednym wycinku aplikacji na zbyt długi czas, zajmę się więc kolejnymi funkcjami a do powyższych wrócę gdy tamte także będą już funkcjonowały na podstawowym poziomie.

Na koniec raz jeszcze podaję link do projektu na moim koncie GitHub (kliknij w pogrubiony tekst)¸ gdzie możesz podejrzeć w jakim momencie tworzenia aplikacji znajduję się teraz. Bardzo chętnie usłyszę i przeczytam wszelkie uwagi na temat mojego kodu, jeśli tylko coś przychodzi ci do głowy – bez krępacji, pisz! 🙂

 

Dodaj komentarz