Models
Class Client
class Client(models.Model):
name = models.CharField('clients name', max_length=128, null=False)
Class Account
class Account(models.Model):
iban = models.CharField('iban', max_length=10, null=False, unique=True)
created = models.DateTimeField('creation date', auto_now_add=True)
closed = models.DateTimeField('closed date', default=None, null=True)
balance = models.FloatField('current balance', default=0, null=False)
owner = models.ForeignKey(Client, null=False)
Class Transaction
class Transaction(models.Model):
timestamp = models.DateTimeField('transaction timestamp', auto_now_add=True)
src = models.ForeignKey('Account', default=None, null=True)
dest = models.ForeignKey('Account', default=None, related_name='target', null=True)
amount = models.FloatField('transaction amount', null=False)
Database Creation and Migration
Pre aplikovanie akejkoveľvek zmeny v modeli alebo modeloch je potrebné vykonať tzv. migráciu. Migrácia zabezpečí aktualizovanie databázovej schémy automaticky vzhľadom na vykonané zmeny bez nutnosti manuálneho zásahu do databázovej schémy (žiadne ručné ALTER TABLE
)
$ ./manage.py makemigrations
$ ./manage.py migrate
Výsledok si môžeme priamo overiť v databáze spustením databázového klienta pomocou nástroja manage.py
a jeho príkazu dbshell
$ ./manage.py db_shell
sqlite> .tables
First Steps
Budeme pracovať z príkazového riadku. Používať budeme príkaz shell_plus z nástroja manage.py
, ktorý spustí ipython
, pokiaľ je nainštalovaný a rovno nahrá aj všetky modely. To je značnou výhodou, nakoľko sa po spustení nemusíme vždy starať o naimportovanie potrebných balíčkov. Taktiež zabezpečí ich znovunačítanie, ak spravíme nejakú zmenu. Občas sa však jeho ukončeniu a znovuspusteniu nevyhneme.
$ ./manage.py shell_plus
SQLite version 3.14.2 2016-09-12 18:50:49
Enter ".help" for usage hints.
sqlite> .tables
account_account auth_user_groups
account_client auth_user_user_permissions
account_transaction django_admin_log
auth_group django_content_type
auth_group_permissions django_migrations
auth_permission django_session
auth_user
sqlite> .schema account_client
CREATE TABLE "account_client" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(128) NOT NULL);
sqlite>
Creating New Client
Vytvorenie nového klienta
client = Client()
client.name = 'jano'
client.id
None
Id (primárny kľúč klienta) začne existovať až potom, ako sa uloží do databázy:
client.save()
client.id
1
Vytvorenie nového klienta zadaním jeho vlastností priamo pri vytváraní
client = Client(name='juraj')
client.save()
Alebo ako one-liner
Client(name='jozef').save()
Checking Results in DB
Kedykoľvek si môžeme overiť výsledky snaženia priamo v databáze
Updating Existing Client
client.id
3
client.name = 'Jozef'
client.save()
Deleting Existing Client
client.delete()
Client Update
Aby sme pri vypisovani konkretneho objektu nevideli jeho reprezentacny tvar ako v prípade inštancie triedy Client
<Client: client object>
vytvoríme si tzv. magickú metódu s názvom __str__()
, ktorá sa bude volať vždy, keď budeme chcieť reťazcovú reprezentáciu daného objektu. Jej návratovou hodnotou je totiž reťazec:
def __str__(self):
return '{}: {}'.format(self.id, self.name)
Account Methods
Vytvorte magickú funkciu __str__()
, ktorá vráti reťazcovú reprezentáciu objektu
def __str__(self):
return '{} ({}) {}'.format(self.iban, self.owner.name, self.balance)
Vytvorte metódu is_open()
, ktorá vráti hodnotu True
, ak je účet otvorený alebo False
, ak nie je
def is_open(self):
return self.closed is None
Vytvorte metódu is_closed()
, ktorá vráti hodnotu True
, ak je účet zatvorený alebo False
, ak zatvorený nie je
def is_closed(self):
return not self.is_open()
Vytvorte metódu withdraw()
, pomocou ktorej zabezpečíte výber požadovanej čiastky z účtu. Prečerpanie účtu riešiť nemusíte, ale výber zabezpečte len v prípade, že je účet otvorený. Ak nie je, skončite s výnimkou týpu ValueError
Po úspešnom výbere vytvorte transakciu, v ktorej uvediete zdrojový účet, z ktorého sú peniaze vyberané a množstvo peňazí, ktoré sú vyberané.
def withdraw(self, amount):
if self.is_closed():
raise ValueError('Account is closed')
self.balance -= amount
self.save()
# make transaction
Transaction(src=self, amount=amount).save()
Vytvorte metódu deposit()
, pomocou ktorej zabezpečíte vklad požadovanej čiastky na účet. Tú však bude možné vložiť len v prípade, ak účet nie je zatvorený. Ak je, skončite s výnimkou typu ValueError
Po úspešnom vklade vytvorte transakciu, v ktorej uvediete cieľový účet, na ktorý sú peniaze vkladané a ich množstvo.
def deposit(self, amount):
if self.is_closed():
raise ValueError('Account is closed')
self.balance += amount
self.save()
# make transaction
Transaction(dest=self, amount=amount).save()
Vytvorte metódu transfer()
, pomocou ktorej budete vedieť previesť peniaze z jedného účtu na druhý. Samozjreme prevod bude možný len v tom prípade, ak účet nie je zatvorený. Samozrejme pre túto operáciu vytvorte samostatnú inštanciu triedy Transakcia
, kde túto transakciu opíšete.
def transfer(self, dest, amount):
# check if accounts are open first
if self.is_closed():
raise ValueError('Source Account is Closed')
if dest.is_closed():
raise ValueError('Destination Account is Closed')
self.amount -= amount
self.save()
dest.amount += amount
dest.save()
# make transaction
Transaction(src=self, dest=dest, amount=amount).save()
Transaction Methods
Vytvorte magickú metódu __str__()
, ktorá vráti reťazcovú reprezentáciu transakcie. A to tak, že:
- ak nie je zadaný cieľový účet, vráťte reťazec s informáciami o výbere (withdraw)
- ak nie je zadaný zdrojový účet, vráťte reťazec s informáciami o vklade (deposit)
- ak sú zadané oba účty, vráťte reťazec s informáciami o prenose (transfer)
def __str__(self):
if self.src is None:
return 'deposit to {} at {}: {}'.format(self.dest, self.timestamp, self.amount)
elif self.dest is None:
return 'withdraw from {} at {}: {}'.format(self.src, self.timestamp, self.amount)
else:
return 'transaction from {} to {} at {}: {}'.format(self.src, self.dest, self.timestamp, self.amount)
TODO
- Model.objects.all()
- Model.objects.get()
- urobit ulohy podla toho, co bude treba:
- ziskat vsetky ucty
- ziskat ucty len daneho (prihlaseneho) pouzivatela
- ziskat transakcie len s prislusnym uctom
- ziskat transakcie len daneho (prihlaseneho) pouzivatela
- validacia formularu