Μια πρώτη ματιά στο Django

Επειδή το Django αναπτύχθηκε σε ένα ειδησεογραφικό περιβάλλον με γρήγορους μεταβαλλόμενα ρυθμούς, σχεδιάστηκε με τέτοιο τρόπο ούτως ώστε οι συνηθισμένες Web εργασίες να διεκπεραιώνονται γρήγορα και εύκολα. Παρακάτω παρουσιάζεται μια γενική εικόνα του πως να γράψετε μια Web εφαρμογή (app) με βάση δεδομένων χρησιμοποιώντας το Django.

Ο στόχος αυτού το άρθρου είναι να σας δώσει μερικά τεχνικά στοιχεία (γνώσεις, αν θέλετε) προκειμένου να καταλάβετε πως λειτουργεί το Django. Δεν αποτελεί, ωστόσο, κάποιον οδηγό ή αναφορά για να ανατρέξετε (παρόλο που τα έχουμε και τα δύο)! Όταν είστε έτοιμοι για να ξεκινήσετε κάποιο project, μπορείτε να ξεκινήσετε με τον οδηγό (tutorial) ή να ανατρέξετε σε πιο λεπτομερείς κείμενα όπως το εγχειρίδιο (documentation) του Django.

Σχεδιάστε το μοντέλο σας

Το Django μπορείτε να το χρησιμοποιήσετε χωρίς τη χρήση κάποιας βάσης δεδομένων (στατικές σελίδες). Από την άλλη, για τη δημιουργία δυναμικών σελίδων, το Django σας δίνει τη δυνατότητα να σχεδιάσετε τη διάταξη της βάσης δεδομένων (database layout) σε κώδικα γραμμένο αποκλειστικά σε Python, με τη χρήση του object-relational mapper το οποίο είναι προεγκατεστημένο.

Το άρθρο σχεδίαση μοντέλων προσφέρει πολλούς τρόπους σχεδίασης και αναπαράστασης των μοντέλων σας – μέχρι τώρα, έχει λύσει πολλών χρόνων προβλήματα που έχουν να κάνουν με τη σχεδίαση του schema της βάσης δεδομένων. Να ένα γρήγορο παράδειγμα:

mysite/news/models.py
from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)

    def __str__(self):              # __unicode__ on Python 2
        return self.full_name

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

    def __str__(self):              # __unicode__ on Python 2
        return self.headline

Εγκαταστήστε το

Επόμενο βήμα είναι να τρέξετε την κατάλληλη εντολή του Django (μέσα από την κονσόλα) ούτως ώστε να δημιουργηθούν αυτόματα οι πίνακες στη βάση δεδομένων:

$ python manage.py migrate

Η εντολή migrate κοιτάζει όλα τα μοντέλα σας και δημιουργεί (αν δεν υπάρχουν) πίνακες στη βάση δεδομένων (database tables). Επίσης, προαιρετικά, παρέχει έναν πλούσιο μηχανισμό ελέγχου του schema της βάσης δεδομένων.

Απολαύστε το δωρεάν API

Με αυτά, έχετε ένα δωρεάν και πλούσιο Python API για να αποκτήσετε πρόσβαση στα δεδομένα σας (που βρίσκονται μέσα στους πίνακες). Το API δημιουργείται “επί ποδός” (on the fly), δεν απαιτείται κώδικας για να το δημιουργήσει:

# Import the models we created from our "news" app
>>> from news.models import Reporter, Article

# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>

# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')

# Save the object into the database. You have to call save() explicitly.
>>> r.save()

# Now it has an ID.
>>> r.id
1

# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'

# Django provides a rich database lookup API.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Reporter matching query does not exist.

# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'

# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()

# Delete an object with delete().
>>> r.delete()

Ένα δυναμικό διαχειριστικό περιβάλλον: δεν είναι απλά οικοδομή – είναι ολόκληρο το σπίτι

Αφού ορίσετε τα μοντέλα σας, το Django μπορεί αυτόματα να δημιουργήσει για εσάς ένα επαγγελματικό, έτοιμο προς παραγωγή (production ready) διαχειριστικό περιβάλλον – ένα website που επιτρέπει σε εξουσιοδοτημένους χρήστες να προσθέσουν, αλλάξουν και διαγράψουν objects. Είναι τόσο εύκολο όσο να καταχωρήσετε (register) τα μοντέλα σας στο admin site:

mysite/news/models.py
from django.db import models

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
mysite/news/admin.py
from django.contrib import admin

from . import models

admin.site.register(models.Article)

Η φιλοσοφία πίσω από το Django admin interface είναι ότι το site σας θα επεξεργάζεται από κάποιο προσωπικό ή πελάτη ή απλά από εσάς τον ίδιο – και εσείς δεν θέλετε να ασχολείστε με τη δημιουργία backend interfaces μόνο και μόνο για να διαχειρίζεστε το περιεχόμενο.

Ένας τυπικός μπούσουλας στη σχεδίαση Django apps είναι να δημιουργείτε μοντέλα και αμέσως μετά να τα καταχωρείτε (register) με το admin site ούτως ώστε να μπορείτε να τα διαχειρίζεστε όσο γίνεται πιο γρήγορα. Έτσι, το προσωπικό σας (ή οι πελάτες σας) θα μπορούν να καταχωρούν δεδομένα (περιεχόμενο) και να αναπτύξουν το τρόπο με το οποίο θα τα παρουσιάσουν στο ευρύ κοινό.

Σχεδίαση των URLs

Μια καθαρή και κομψή σχεδίαση του URL αποτελεί σημαντική λεπτομέρεια για μια υψηλών προδιαγραφών Web εφαρμογή. Το Django ενθαρρύνει τον όμορφο URL σχεδιασμό και δεν εισάγει άσχημες καταλήξεις στα URLs, όπως .php ή .asp.

Για να σχεδιάσετε URLs για ένα app, θα πρέπει να δημιουργήσετε ένα Python module το οποίο θα λέγεται URLconf. Θα αναπαριστά ένα πίνακα περιεχομένων του app σας. Θα περιέχει μια απλή αντιστοίχιση μεταξύ URL πατρόν (patterns) και Python callback συναρτήσεων. Τα URLconfs χρησιμεύουν, επίσης, στο να αποσυνδέσουν τα URLs (ολόκληρα τα paths, π.χ /example/info/contact) από τον Python κώδικα.

Ένα URLconf module θα έδειχνε κάπως έτσι, αναφορικά με το παράδειγμα Reporter/Article πιο πάνω:

mysite/news/urls.py
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

Ο παραπάνω κώδικας αντιστοιχεί τα URLs, ως απλές regular expressions, στην τοποθεσία των Python callback συναρτήσεων («views»). Οι regular expressions χρησιμοποιούν παρενθέσεις για να «αιχμαλωτίσουν» τις τιμές από τα URLs. Όταν ο χρήστης ζητάει (requests) να δει μια σελίδα, το Django ανατρέχει με τη σειρά κάθε URL pattern και σταματάει στο πρώτο που θα ταιριάξει με το ζητούμενο URL. (Αν δεν ταιριάξει κανένα, τότε το Django καλεί ένα view με το ειδικό όνομα-αριθμό 404). Αυτή η διαδικασία είναι εξαιρετικά γρήγορη, επειδή οι regular expressions μεταγλωττίζονται όταν φορτώνονται (compiled at load time).

Once one of the regexes matches, Django calls the given view, which is a Python function. Each view gets passed a request object – which contains request metadata – and the values captured in the regex.

Για παράδειγμα αν ο χρήστης ζήτησε το URL «/articles/2005/05/39323/», το Django θα καλούσε τη συνάρτηση-view news.views.article_detail(request, '2005', '05', '39323').

Γράψτε τα views σας

Κάθε view είναι υπεύθυνο να κάνει ένα από δύο πράγματα: Θα επιστρέφει ένα HttpResponse object το οποίο θα περιέχει τα δεδομένα της ζητούμενης σελίδας ή θα κάνει raise κάποιο exception όπως το Http404. Τα υπόλοιπα άπτονται σε εσάς.

Γενικά, ένα view ανακτά τα δεδομένα ανάλογα τις παραμέτρους, φορτώνει το template και κάνει render το template με τα δεδομένα που ανέκτησε. Αναφερόμενοι στο παραπάνω παράδειγμα και πιο συγκεκριμένα στο πρώτο URL regex, θα υλοποιήσουμε το year_archive view:

mysite/news/views.py
from django.shortcuts import render

from .models import Article

def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

Αυτό το παράδειγμα χρησιμοποιεί το template system του Django, το οποίο παρέχει πολλά ισχυρά χαρακτηριστικά και παράλληλα προσπαθεί να παραμείνει απλό στη χρήση του για αυτούς που δεν είναι προγραμματιστές.

Σχεδιάστε τα templates σας

Ο κώδικας παραπάνω φορτώνει το template με το όνομα news/year_archive.html.

Το Django έχει ειδική μηχανή αναζήτησης template, η οποία επιτρέπει στην ελαχιστοποίηση της επαναληπτικότητας (redundancy) ανάμεσα στα templates. Στις ρυθμίσεις (settings) του Django, καθορίζετε μία λίστα από φακέλους (directories) στους οποίους θα κοιτάξει το Django να βρει το αντίστοιχο template αρχείο. Η ρύθμιση αυτή γίνεται μέσω του DIRS. Αν ένα template δεν βρεθεί στον πρώτο φάκελο τότε εξερευνάται ο δεύτερος κοκ.

Ας υποθέσουμε ότι το template news/year_archive.html βρέθηκε. Αυτό θα μοιάζει κάπως έτσι:

mysite/news/templates/news/year_archive.html
{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}
    <p>{{ article.headline }}</p>
    <p>By {{ article.reporter.full_name }}</p>
    <p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

Οι μεταβλητές περιβάλλονται από διπλές αγκύλες. Το {{ article.headline }} σημαίνει «Δώσε μου την τιμή του headline attribute του object article». Αλλά οι τελείες δεν χρησιμοποιούνται μόνο για να ανακαλούμε τα attributes ενός object. Χρησιμεύουν επίσης και για να ψάχνουμε μέσα σε Python dictionaries, μέσα σε Python λίστες (lists) καθώς και για να καλούμε μεθόδους ενός object.

Σημειώστε ότι το {{ article.pub_date|date:"F j, Y" }} χρησιμοποιεί ένα στυλ του Unix που λέγεται «pipe» (ο χαρακτήρας «|»). Αυτό ονομάζεται template filter και είναι ένας τρόπος να φιλτράρουμε την τιμή ή την μεταβλητή. Στην συγκεκριμένη περίπτωση, το φίλτρο με το όνομα “date” φιλτράρει το Python datetime object ούτως ώστε να παρουσιαστεί σε μία συγκεκριμένη μορφή (σύμφωνα με την συνάρτηση date της γλώσσας PHP).

Μπορείτε να συνδέσετε (chain) περισσότερα από ένα φίλτρα, ανάλογα τις απαιτήσεις σας. Μπορείτε να γράψετε δικά σας template filters. Μπορείτε να γράψετε δικά σας template tags, τα οποία θα τρέχουν το δικό σας Python κώδικα στο παρασκήνιο.

Εν κατακλείδι, το Django χρησιμοποιεί την έννοια του «template inheritance». Αν προσέξατε, στην αρχή του template υπάρχει το {% extends "base.html" %}. Αυτό σημαίνει «πρώτα φόρτωσε το template με το όνομα “base.html”, το οποίο “base” έχει ορίσει κάποια τμήματα blocks (όπως είναι το title και το content) και αντικατέστησε τα κομμάτια αυτά του “base.html” με αυτά του year_archive.html». Με άλλα λόγια, το Django template system ελαχιστοποιεί στο έπακρο την επαναληπτικότητα ανάμεσα στα template σας: κάθε template θα πρέπει να ορίζει μόνο ότι είναι μοναδικό στο δικό του template.

Δείτε και το «base.html» template, συμπεριλαμβανομένου και του static files template tag:

mysite/templates/base.html
{% load static %}
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <img src="{% static "images/sitelogo.png" %}" alt="Logo" />
    {% block content %}{% endblock %}
</body>
</html>

Το παραπάνω template, σε γενικές γραμμές και πολύ απλοϊκά, ορίζει το πως θα φαίνεται η σελίδα (μαζί με το logo του site) και υποδηλώνει τις «τρύπες» (block title και block content) τις οποίες θα «γεμίσουν» τα child templates. Αυτό κάνει τον τυχόν ανασχεδιασμό του site τόσο εύκολο όσο το να αλλάξετε μόνο ένα αρχείο – το base template.

Σας επιτρέπει, επίσης, να δημιουργήσετε διαφορετικές εκδόσεις του site σας, με διαφορετικά base templates, ενώ παράλληλα εσείς επαναχρησιμοποιείτε τα ίδια child templates. Οι δημιουργοί του Django’s χρησιμοποιούν αυτή την τεχνική για να δημιουργήσουν εκπληκτικές διαφορετικές mobile εκδόσεις των sites – απλά και μόνο δημιουργώντας καινούργιο base template.

Σημειώστε επίσης ότι δεν χρειάζεται να χρησιμοποιήσετε το template system του Django αν δεν σας ταιριάζει. Ενώ δουλεύει και επικοινωνεί εξαιρετικά με το model layer του Django, μπορείτε να χρησιμοποιήσετε κάποιο άλλο template system. Με την ίδια λογική μπορείτε να αλλάξετε και το API για την επικοινωνία με την βάση δεδομένων. Μπορείτε να δουλέψετε με άλλο abstraction layer βάσης δεδομένων, να διαβάζετε XML αρχεία, να διαβάζετε αρχεία εκτός δίσκου ή οτιδήποτε θέλετε. Κάθε κομμάτι του Django – models, views, templates – είναι αποσυνδεδεμένο με το επόμενο.

Και αυτό είναι μόνο η επιφάνεια

Αυτό το άρθρο ήταν μόνο μια γρήγορη προεπισκόπηση των δυνατοτήτων και λειτουργιών του Django. Μερικά πιο χρήσιμα χαρακτηριστικά είναι:

  • Το caching framework το οποίο ενσωματώνεται με το memcached ή άλλα backends.
  • Το syndication framework που βοηθάει στη δημιουργία RSS και Atom feeds τόσο εύκολα όσο να γράψετε μια μικρή Python class.
  • Περισσότερα αυτοματοποιημένα διαχειριστικά (admin) χαρακτηριστικά – αυτή η περιληπτική παρουσίαση απλά ξύνει την επιφάνεια.

Τα επόμενα βήματα για σας, στην παρούσα φάση, είναι να κατεβάσετε το Django, να διαβάσετε τους οδηγούς (tutorials) και να συμμετάσχετε στην κοινότητα. Ευχαριστούμε για το ενδιαφέρον!

Back to Top