Professional Documents
Culture Documents
Η εφαρμογή «το βήμα των χρηστών» (pitch από εδώ και πέρα) αποτελείται από χρήστες (users)
και τα μηνύματά τους (posts). Θα προσπαθήσουμε να αναπτύξουμε την εφαρμογή στο δυνατό
λιγότερο χρόνο.
Μοντελοποίηση users
• μοναδικό id
• όνομα
• επώνυμο
• διεύθυνση email και
• συνθηματικό
(Στην πραγματικότητα επίσης θα περιλαμβάνει ένα registration_key, καθώς επίσης και ένα
reset_password_key, αλλά δεν χρειάζεται να τα ξέρουμε και όλα, έτσι;)
Μοντελοποίηση posts
• μοναδικό id
• το περιεχόμενο (content) του μηνύματος και
• το user_id του χρήστη που ανάρτησε το μήνυμα
Όπως έχετε ήδη αναγνωρίσει, οι δύο πίνακες (μοντέλα για το web2py) παρουσιάζουν μια
συγκεκριμένη σχέση. Ένας χρήστης μπορεί να γράψει από κανένα έως έναν απεριόριστο αριθμό
μηνυμάτων, ενώ κάθε μήνυμα γράφεται από (ανήκει σε) έναν και μόνο έναν χρήστη.
2.2 Ανάπτυξη
Στο προηγούμενο μάθημα δημιουργήσαμε μια καινούρια εφαρμογή από το γραφικό περιβάλλον
web του framework.Ας δούμε τώρα ένα διαφορετικό τρόπο να δημιουργήσουμε μια εφαρμογή
εκκίνησης. Στη γραμμή εντολών του τερματικού σας μπείτε στον κατάλογο του web2py και δώστε
τις εξής εντολές:
1. C:
2. cd\
3. cd web2py.dat
4. python web2py.py –S pitch
Εφόσον εφαρμογή με τέτοιο όνομα δεν υπάρχει, το framework θα αποκριθεί πληροφορώντας μας
γι’ αυτό και θα ρωτήσει εάν θέλουμε να δημιουργηθεί μια εφαρμογή εκκίνησης με αυτό το όνομα.
Απαντήστε ‘yes’ (ή ‘y’) στην ερώτηση. Η εφαρμογή pitch θα δημιουργηθεί και το web2py θα μας
εισάγει σε ένα κέλυφος python (python shell από εδώ και πέρα) αναμένοντας εντολές. Προς το
παρόν πατήστε Ctrl + D και “yes” για να βγείτε από το python shell.
Είναι ώρα να δημιουργήσουμε τα μοντέλα μας σύμφωνα με το σχέδιο που κάναμε κατά τη
σχεδίαση της εφαρμογής. Πρέπει δηλαδή να δημιουργήσουμε το μοντέλο user και το μοντέλο post.
Τα καλά νέα είναι ότι το web2py καθόρισε κατευθείαν το μοντέλο user κατά τη διάρκεια
δημιουργίας της εφαρμογής εκκίνησης. Πρόκειται για τον πίνακα auth_user που ανήκει στο
μοντέλο db, αναφέρεται δε ως db.auth_user.1 Προς το παρόν, το μοντέλο αυτό είναι αρκετό. Για πιο
σύνθετες εφαρμογές το web2py προσφέρει εργαλεία για να τροποποιήσουμε τα μοντέλα μας και να
τα προσαρμόσουμε στις ανάγκες μας.
Με το notepad++ ανοίξτε το αρχείο db.py που βρίσκεται στο folder models και στο τέλος του
προσθέστε τον εξής κώδικα:
94. db.define_table('post',
95. Field('minima', 'text'),
96. Field('user_id', db.auth_user)
97. )
Αυτό που μόλις κάναμε είναι να ορίσουμε ένα πίνακα με δύο πεδία: ένα πεδίο τύπου σημειώσεων
(text) και ένα πεδίο αναφοράς (‘foreign key’ για τους πιο ψαγμένους στις βάσεις δεδομένων) το
οποίο παραπέμπει (συνδέει) κάθε μήνυμα με κάποια εγγραφή στον πίνακα των χρηστών (user). Το
πεδίο id για τον πίνακα post δεν χρειάζεται να το ορίσουμε, καθώς δημιουργείται αυτόματα από το
web2py - όπως άλλωστε συμβαίνει και για όλους τους πίνακες που δημιουργούνται από το
framework στη βάση δεδομένων.
1
Για τη αναπαράσταση της βάσης δεδομένων στην εφαρμογή μας (μοντελοποίηση, db) θα μιλήσουμε αργότερα.
Post – άρετε ελεύθερα!
Για να μπορέσει ο χρήστης μας να αναρτήσει ένα μήνυμα στο site, χρειάζεται να δημιουργήσουμε
ένα κατάλληλο ενδιάμεσο διεπαφής (interface). Αυτό δεν θα είναι τίποτε άλλο παρά μια ιστοσελίδα
με μια φόρμα, την οποία θα μπορεί ο χρήστης να συμπληρώνει και να υποβάλλει.
Γρήγορα, στο notepad++ και ανοίγουμε το αρχείο default.py που βρίσκεται στο folder
controllers2. Δημιουργήστε μια συνάρτηση ονομάζοντάς την ‘enter_post()’ στο τέλος του αρχείου:
1. def enter_post():
2. “““Επιστρέφει μια φόρμα για εισαγωγή μηνυμάτων”””
3. formForMessage = crud.create(db.post)
4. return dict(form=formForMessage)
Με τη δημιουργία της φόρμας εισαγωγής, ουσιαστικά γράψαμε σε γλώσσα Python την πρώτη μας
υπο-ρουτίνα3, η οποία έρχεται πάντα υπό το κέλυφος μιας συνάρτησης. Θα επανέλθουμε στις
συναρτήσεις αργότερα. Προς το παρόν κρατήστε ότι η πρώτη γραμμή κατά τον ορισμό τους αρχίζει
με def και τελειώνει με ‘:’ ενώ το υπόλοιπο σώμα της συνάρτησης πρέπει να ακολουθεί τη
σύμβαση εσοχών της Python.
Στη δεύτερη γραμμή της συνάρτησης enter_post() δημιουργούμε τη φόρμα εισαγωγής μηνυμάτων
καλώντας ένα στιγμιότυπο (instance) του αντικειμένου CRUD4 του web2py. Πρόκειται για ένα
τυποποιημένο τρόπο χειρισμού εγγραφών στις βάσεις δεδομένων. Το web2py υποστηρίζει κι
άλλους πιο κομψούς ή πολύπλοκους μηχανισμούς, αλλά προς το παρόν θα αρκεστούμε στον
CRUD. Η τελευταία γραμμή της συνάρτησης επιστρέφει τη φόρμα που φτιάξαμε ως αντικείμενο
στην αντίστοιχη view.
2
Όπως ίσως παρατηρείτε, από εδώ και πέρα θα ανοίγουμε τα διάφορα αρχεία με εξειδικευμένους επεξεργαστές κειμένων
(όπως το notepad++) και όχι με το υποσύστημα επεξεργασίας του web2py.
3
Υπο-Ρουτίνα (Wikipedia): Στην επιστήμη των υπολογιστών, μια υπο-ρουτίνα (που επίσης καλείται διαδικασία,
συνάρτηση, ρουτίνα, μέθοδος ή υποπρόγραμμα) είναι τμήμα κώδικα μέσα σε ένα μεγαλύτερο πρόγραμμα το οποίο
διεκπεραιώνει κάποια συγκεκριμένη αποστολή και είναι σχετικά ανεξάρτητο από τον υπόλοιπο κώδικα.
4
CRUD (Wikipedia): Στον προγραμματισμό, οι τέσσερις βασικές ρουτίνες αλληλεπίδρασης με ένα σύστημα μόνιμης
αποθήκευσης δεδομένων (database) είναι οι Create, Read, Update and Delete (CRUD). Σε κάποιες περιπτώσεις η
CRUD επεκτείνεται ανταλλάσσοντας τους όρους ‘read’ και ‘delete’με τους ‘retrieve’ και ‘destroy’ αντίστοιχα. Ο όρος
CRUD συχνά επίσης χρησιμοποιείται για να περιγράψει αντικείμενα διεπαφής τα οποία διευκολύνουν τη θέαση, την
αναζήτηση τη διαγραφή και την επικαιροποίηση πληροφοριών μέσω φορμών και αναφορών σε υπολογιστές.
Παρατηρούμε ότι το framework έχει χρησιμοποιήσει ως ετικέτες τα ονόματα των πεδίων, όπως
αυτά ορίσθηκαν κατά τη δημιουργία των μοντέλων auth_user και post. Μονολιθικό; Για να
δούμε…
Ακόμη στο notepad++, ανοίξτε πάλι το αρχείο db.py (θυμάστε πού βρίσκεται;), τροποποιήστε το
μοντέλο του πίνακα post ως εξής:
1. db.define_table('post',
2. Field('minima', 'text', label = ‘Μήνυμα’),
3. Field('user_id', db.auth_user)
)
… αρκεί να έχει πρόσβαση! Θα εισάγουμε στη φόρμα τον περιορισμό να επιτρέπεται η εισαγωγή
μηνυμάτων μόνο σε εξουσιοδοτημένους χρήστες. Απλό:
1. @auth.requires_login()
2. def enter_post():
3. “““Επιστρέφει μια φόρμα για εισαγωγή μηνυμάτων”””
4. formForMessage = crud.create(db.post)
5. return dict(form=formForMessage)
Ουσιαστικά προσθέσαμε τον κώδικα @auth.requires_login() μια γραμμή ακριβώς επάνω από τη
συνάρτηση (χωρίς να μεσολαβεί κενή γραμμή). Η λειτουργία της είναι να απαιτεί Login από όποιον
χρήστη επιχειρεί να ανοίξει το αντίστοιχο view. Η εντολή αυτή, παρότι έξω από τη συνάρτηση,
αποτελεί αναπόσπαστο κομμάτι αυτής. Δεν έχει ενέργεια σε καμιά άλλη. Τέτοιες γραμμές
καλούνται «διακοσμητές» (decorators), αρχίζουν πάντα με ‘@’ και βρίσκονται ακριβώς επάνω από
τον ορισμό της συνάρτησης. Ένας πολύ χρήσιμος τέτοιος διακοσμητής που θα χρησιμοποιείτε
συχνά είναι ο @auth.requires_membership(‘something’). Όπως δείχνει το όνομά του, ο χρήστης
δεν αρκεί μόνο να κάνει login, αλλά απαιτείται επίσης να ανήκει και σε συγκεκριμένο/α group/s για
να έχει πρόσβαση στις διάφορες περιοχές του μοντέλου μας. Σε περίπτωση που μη
εξουσιοδοτημένος χρήστης επιχειρήσει να προσπελάσει μια προστατευμένη σελίδα, το web2py θα
τον ενημερώσει με ένα μήνυμα flash.
Εάν ανανεώσετε τη σελίδα, θα εμφανισθεί μια φόρμα Login στην οποία θα πρέπει να δώσετε τα
email/password που δηλώσατε κατά την εγγραφή σας, πριν το σύστημα δεχθεί οποιαδήποτε
καταχώρηση μηνύματος εκ μέρους σας.
Σαν ένα τελευταίο βήμα, θα τροποποιήσουμε την εφαρμογή μας ώστε να δείχνει τους χρήστες και
τα μηνύματά τους στην πρώτη σελίδα της.
1. def index():
2. """Δείχνει τους χρήστες και τα μηνύματά τους"""
3. users = db(db.auth_user.id > 0).select()
4. posts = db(db.post.id > 0).select()
5. return dict(users=users, posts=posts)
Στην πρώτη σελίδα του site θα φαίνονται όλοι οι χρήστες και τα μηνύματά τους:
Το menu παρακαλώ…
Στο σημείο αυτό θα προσθέσουμε ένα κεντρικό menu πλοήγησης στην εφαρμογή μας.
Ανοίξτε το αρχείο menu.py που βρίσκεται στο folder models βρείτε το τμήμα που αναφέρεται στο
Menu και αλλάξτε τον ως εξής:
1. response.menu = [
['Αρχική',False,URL('default','index')],
['Εισαγωγή Μηνυμάτων',False,URL('default','enter_post'),[]]
]
Το αντικείμενο response.menu είναι υπεύθυνο για την εμφάνιση του κεντρικού menu πλοήγησης
στις σελίδες της εφαρμογής μας. Πρόκειται για μια δομή λίστας, κάθε αντικείμενο της οποίας
αποτελείται από υπο-λίστες, κάθε μία από τις οποίες αντιπροσωπεύει μια επιλογή του κεντρικού
menu. Σε κάθε υπο-λίστα:
• σε κάθε υπο-λίστα υπάρχει προαιρετικά και ένα τελευταίο μέλος, μια υπο-υπο-λίστα. Αυτή
χρησιμοποιείται για να αποκτήσει νέα μέλη η επιλογή αυτή του κεντρικού menu (δενδροειδής
μορφή του menu), με τον ίδιο ακριβώς τρόπο.
Αποδεχθείτε το τώρα, για να μην απογοητευθείτε: τις περισσότερες φορές, στην αρχή τουλάχιστον,
θα κάνετε πολλά τυπογραφικά λάθη (μπορεί και λάθη ροής ή λογικά). Κατά συνέπεια θα έρχεστε
συχνά αντιμέτωποι με το σύστημα διόρθωσης λαθών του web2py που, πιστέψτε με, είναι ο
καλύτερός σας φίλος. Προσπαθεί να αναλύσει τον κώδικά σας και να σας κατευθύνει όσο το
δυνατό σωστότερα προς την κατάλληλη λύση.
Ας προσομοιώσουμε ένα τέτοιο λάθος για να δούμε πώς δουλεύει η ιστορία αυτή: μετατρέψτε τη
συνάρτηση enter_post() στον controller default.py ως εξής:
1. @auth.requires_login()
2. def enter_post():
3. “““Επιστρέφει μια φόρμα για εισαγωγή μηνυμάτων”””
4. formForMessage = crid.create(db.post)
5. return dict(form=formForMessage)
…κάναμε λάθος και αντί ‘crud’ πληκτρολογήσαμε ‘crid’ (σειρά 4). Όταν επισκεφθούμε τη σελίδα
http://127.0.0.1:8000/pitch/default/enter_post το web2py θα ζητήσει τα διαπιστευτήριά μας και στη
συνέχεια θα εκδώσει το εξής εισιτήριο λάθους:
Στο σημείο αυτό θα επεξηγηθεί η αρχή λειτουργίας του framework. Ίσως να αναρωτιέστε τι στην
ευχή κάνει το web2py με τους controllers, τις συναρτήσεις τους, τα views και τα μοντέλα.
Συνοπτικά, το framework χρησιμοποιεί ένα μηχανισμό διεκπεραίωσης (dispatching mechanism) για
να χειριστεί μια δεδομένη διεύθυνση (url). Κατά συνθήκη, μια διεύθυνση για το web2py έχει την
εξής μορφή:
http://hostname:port/application/controller/function/args?vars
Για παράδειγμα, για την εφαρμογή Pitch που μόλις γράψαμε, αυτό σημαίνει:
http://127.0.0.1:8000/pitch/default/enter_post
όπου
• 127.0.0.1:8000 = hostname:port
• pitch = application
• default = controller
• enter_post = function
Όταν το web2py δει μια τέτοια διεύθυνση κατευθείαν ψάχνει στον κατάλογο applications για
εφαρμογή που να ονομάζεται pitch. Εφόσον τη βρει, ανοίγει τον controller default και καλεί τη
συνάρτηση enter_post.
Στη συνέχεια η συνάρτηση enter_post αλληλεπιδρά με το μοντέλο και στέλνει τα
αποτελέσματα στο αντίστοιχο view μέσω του οποίου δημιουργείται η ιστοσελίδα που τελικά
αποστέλλεται στον περιηγητή του χρήστη.
Τα args και vars δεν τα έχουμε χρησιμοποιήσει ακόμη. Θα μπορούσαν να είναι για παράδειγμα
το id ενός χρήστη, ή κάτι που ο χρήστης έχει δηλώσει σε μια άλλη σελίδα της εφαρμογής μας.
Άσκηση: Εισάγετε ένα καινούριο χρήστη και μερικά μηνύματα για το χρήστη αυτόν.
Άσκηση: Αλλάξτε τίτλο, υπότιτλο και υποσέλιδο των ιστοσελίδων της εφαρμογής σας με τα
εξής:
Άσκηση: Προσθέστε δύο ακόμη σελίδες στην εφαρμογή σας. Στην πρώτη να φαίνονται μόνο
τα μηνύματα του ενός χρήστη και στη δεύτερη μόνο του άλλου.
Άσκηση: Προσθέστε μια καταχώριση με την ονομασία «Μηνύματα χρηστών» στο κεντρικό
menu. Η καταχώριση αυτή δεν πρέπει να δείχνει σε καμιά σελίδα, αλλά θα πρέπει να
περιλαμβάνει δύο επιλογές, μια για κάθε σελίδα που δημιουργήσατε στην
προηγούμενη άσκηση (με κατάλληλες ετικέτες).
Άσκηση: Καταργήστε την προηγούμενη εφαρμογή σας στο server shadow και αναρτήστε τη
νέα με την ίδια ονομασία (pitch_<το όνομα του χρήστη σας στο δίκτυο>).