Γράφοντας το πρώτο σας Django app, μέρος 7

This tutorial begins where Tutorial 6 left off. We’re continuing the web-poll application and will focus on customizing Django’s automatically-generated admin site that we first explored in Tutorial 2.

Που να ψάξετε για βοήθεια

If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.

Παραμετροποιώντας την admin form

Κάνοντας register το Question model με το Django admin (admin.site.register(Question)), το Django ήταν σε θέση να κατασκευάσει μια προεπιλεγμένη εμφάνιση της φόρμας του μοντέλου για επεξεργασία. Με άλλα λόγια σας δίνει τη δυνατότητα να δημιουργείτε, επεξεργάζεστε, ανανεώνετε και διαγράφετε entries στη βάση δεδομένων σας (υπενθυμίζουμε ότι κάθε instance του μοντέλου σας αναπαριστά και μια γραμμή -entry, row- στον αντίστοιχο πίνακα της database) χωρίς τη χρήση της κονσόλας (γραμμής εντολών). Πολύ συχνά θα θέλετε να επεξεργαστείτε την εμφάνιση της φόρμας αυτής καθώς και τον τρόπο που λειτουργεί. Για να το πετύχετε αυτό δεν έχετε παρά να πείτε στο Django τις επιλογές-ρυθμίσεις που θέλετε, για αυτό το μοντέλο, την ώρα που κάνετε register το μοντέλο σας με το Django admin.

Ας δούμε πως δουλεύει αναδιοργανόνοντας τα πεδία (fields) στην φόρμα επεξεργασίας (edit form). Μέσα στο αρχείο polls/admin.py, αντικαταστήστε την γραμμή admin.site.register(Question) με αυτό το κομμάτι κώδικα:

polls/admin.py
from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ["pub_date", "question_text"]


admin.site.register(Question, QuestionAdmin)

Θα ακολουθείτε αυτή τη διαδικασία (αρχικά θα δημιουργείτε μια model admin class και έπειτα θα περνάτε αυτή τη κλάση ως δεύτερο όρισμα στη μέθοδο admin.site.register()) κάθε φορά που θέλετε να αλλάξετε τυχόν επιλογές στο admin (admin options) για ένα μοντέλο.

Αν θυμάστε, πριν την αλλαγή αυτή, στη φόρμα επεξεργασίας εμφανιζόταν πρώτα το πεδίο της ερώτησης και μετά το πεδίο της ημερομηνίας επειδή τα είχαμε δηλώσει με αυτή τη σειρά στο μοντέλο Question. Τώρα, παρακάμπτουμε αυτή τη σειρά και πλέον εμφανίζεται πρώτα το πεδίο της ημερομηνίας («Publication date») και κατόπιν το πεδίο της ερώτησης («Question»):

Fields have been reordered

Αυτό δεν είναι και τόσο εντυπωσιακό με μόλις δύο πεδία, αλλά για φόρμες admin (admin forms) με δεκάδες πεδία, η επιλογή της σειράς εμφάνισης αποτελεί σημαντική λεπτομέρεια.

Και μιλώντας για φόρμες με δεκάδες πεδία, ίσως να θέλετε να διαχωρίσετε τη φόρμα σε πεδία φορμών (fieldsets):

polls/admin.py
from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Date information", {"fields": ["pub_date"]}),
    ]


admin.site.register(Question, QuestionAdmin)

Το πρώτο element από κάθε tuple μέσα στη λίστα fieldsets είναι ο τίτλος του fieldset. Δείτε πως θα εμφανίζεται τώρα η φόρμα:

Form has fieldsets now

Παραμετροποιώντας την admin change list

Τώρα που η διαχειριστική σελίδα του μοντέλου Question δείχνει όμορφη, ας κάνουμε μερικές αλλαγές στην σελίδα «change list» – αυτή που εμφανίζει όλες τις ερωτήσεις μέσα στο σύστημα (σαν μια λίστα).

Δείτε πως φαίνεται σε αυτό το σημείο:

Polls change list page

Από προεπιλογή, το Django εμφανίζει τη μέθοδο str() για κάθε object. Αλλά μερικές φορές θα ήταν πιο βολικό να εμφανίζουμε μεμονομένα πεδία. Για να το κάνουμε αυτό θα χρησιμοποιήσουμε την επιλογή-ρύθμιση list_display, η οποία είναι ένα tuple από ονόματα πεδίων (του μοντέλου σας), τα οποία θα εμφανιστούν ως στήλες σε αυτή τη σελίδα:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date"]

For good measure, let’s also include the was_published_recently() method from Tutorial 2:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date", "was_published_recently"]

Τώρα η σελίδα change list του Question δείχνει κάπως έτσι:

Polls change list page, updated

Μπορείτε να κλικάρετε στους headers κάθε στήλης για να ταξινομήσετε την αντίστοιχη στήλη κατά τις τιμές της. Μοναδική εξαίρεση στη δυνατότητα της ταξινόμηση μιας στήλης αποτελεί η περίπτωση του header was_published_recently, επειδή η ταξινόμηση με βάση την έξοδο μιας μεθόδου (ενός μοντέλου) δεν υποστηρίζεται. Επίσης, σημειώστε ότι ο header της στήλης was_published_recently είναι, από προεπιλογή, το όνομα της μεθόδου (με τα κενά να αντικαθιστούν τις κάτω παύλες) και κάθε κελί της στήλης αυτής περιέχει την έξοδο της συγκεκριμένης μεθόδου (True ή False).

You can improve that by using the display() decorator on that method (in polls/models.py), as follows:

polls/models.py
from django.contrib import admin


class Question(models.Model):
    # ...
    @admin.display(
        boolean=True,
        ordering="pub_date",
        description="Published recently?",
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

For more information on the properties configurable via the decorator, see list_display.

Επεξεργαστείτε το αρχείο polls/admin.py για ακόμη μια φορά και προσθέστε ένα φίλτρο στη σελίδα change list του μοντέλου Question χρησιμοποιώντας το list_filter. Προσθέστε την ακόλουθη γραμμή κώδικα στην κλάση QuestionAdmin:

list_filter = ["pub_date"]

Αυτό προσθέτει μια πλευρική στήλη (sidebar) «Filter» η οποία επιτρέπει το φιλτράρισμα των αποτελεσμάτων στην σελίδα change list κατά το πεδίο pub_date:

Polls change list page, updated

Ο τύπος του φίλτρου που εμφανίζεται εξαρτάται από τον τύπο του πεδίου που προσπαθείτε να φιλτράρετε. Επειδή το πεδίο pub_date είναι τύπου DateTimeField, το Django ξέρει ότι πρέπει να του δώσει τις ανάλογες επιλογές για φιλτράρισμα, όπως: «Οποιαδήποτε ημερομηνία», «Σήμερα», «Τελευταίες 7 μέρες», «Αυτόν το μήνα», «Αυτόν το χρόνο».

Αρχίζει και παίρνει σχήμα η όλη σελίδα μας. Ας προσθέσουμε τη δυνατότητα του searching:

search_fields = ["question_text"]

Αυτό προσθέτει ένα search box κοντά στην κορυφή της σελίδας change list. Όταν κάποιος πληκτρολογήσει κάποια λέξη κλειδί για εύρεση, το Django θα ψάξει μέσα στο πεδίο question_text. Μπορείτε να χρησιμοποιήσετε όσα πεδία θέλετε – όμως επειδή η μέθοδος αυτή κάνει χρήση του LIKE query στο παρασκήνιο, αν περιορίσετε τον αριθμό των search fields μέσα στο πεδίο search_fields, τότε θα κάνει τη δουλειά της database σας πιο εύκολη στην εύρεση της λέξης κλειδί που δώσατε.

Τώρα είναι μια καλή στιγμή να σημειώσουμε ότι η σελίδες change lists σας δίνουν δωρεάν τη δυνατότητα του pagination. Από προεπιλογή, το Djoango εμφανίζει 100 γραμμές ανά σελίδα. Τα attributes Change list pagination, search boxes, filters, date-hierarchies και column-header-ordering συνεργάζονται μεταξύ τους όπως ακριβώς νομίζετε.

Παραμετροποιώντας την εμφάνιση του admin site

Βασικά, η λέξη «Διαχείριση Django» στην κορυφή κάθε σελίδας του admin είναι γελοία. Στην πραγματικότητα είναι ένα κείμενο placeholder.

You can change it, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system.

Παραμετροποιώντας τα templates του project σας

Δημιουργήστε έναν φάκελο templates μέσα στο root φάκελο του project σας (αυτόν που περιέχει το αρχείο manage.py). Τα templates μπορούν να υπάρχουν οπουδήποτε μέσα στο filesystem σας αρκεί το Django να έχει πρόσβαση σε αυτά. (Το Django τρέχει υπό τον χρήστη που τρέχει και τον server σας.) Ωστόσο, το να κρατάτε τα templates σας μέσα στο project σας είναι μια, γενικά, καλή πρακτική.

Ανοίξτε το αρχείο ρυθμίσεων-επιλογών του project σας (settings file, mysite/settings.py) και προσθέστε την επιλογή DIRS μέσα στην επιλογή TEMPLATES:

mysite/settings.py
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

Η επιλογή DIRS είναι μια λίστα με strings. Κάθε string είναι η διαδρομή (path) η οποία καταλήγει σε κάποιο φάκελο που περιέχει τα templates σας. Όταν το Django φορτώνει τα templates θα ψάξει και σε αυτά τα paths για να βρει τα templates σας. Με άλλα λόγια αποτελεί ένα μονοπάτι ευρέσεως των templates.

Οργανώνοντας τα templates

Just like the static files, we could have all our templates together, in one big templates directory, and it would work perfectly well. However, templates that belong to a particular application should be placed in that application’s template directory (e.g. polls/templates) rather than the project’s (templates). We’ll discuss in more detail in the reusable apps tutorial why we do this.

Now create a directory called admin inside templates, and copy the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into that directory.

Που είναι ο πηγαίος κώδικας του Django?

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

$ python -c "import django; print(django.__path__)"
...\> py -c "import django; print(django.__path__)"

Then, edit the file and replace {{ site_header|default:_('Django administration') }} (including the curly braces) with your own site’s name as you see fit. You should end up with a section of code like:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

Χρησιμοποιούμε αυτή τη διαδικασία για να σας δείξουμε πως μπορείτε να κάνετε override τα templates. Σε ένα πραγματικό project, το πιο πιθανόν είναι να χρησιμοποιήσετε το attibute django.contrib.admin.AdminSite.site_header κάνοντας την παραπάνω διαδικασία ακόμα πιο εύκολη.

Αυτό το αρχείο template περιέχει αρκετό κείμενο όπως {% block branding %} και {{ title }}. Τα tags {% και {{ είναι μέρος της γλώσσας template του Django. Όταν το Django κάνει render το αρχείο admin/base_site.html, αυτή η γλώσσα θα τρέξει και θα γεμίσει αυτά τα tags με διάφορες τιμές για να παραχθεί στο τέλος η HTML σελίδα που θα επιστρέψει πίσω στον χρήστη (ως response), όπως είδαμε στον Οδηγό 3.

Note that any of Django’s default admin templates can be overridden. To override a template, do the same thing you did with base_site.html – copy it from the default directory into your custom directory, and make changes.

Παραμετροποιώντας τα templates της εφαρμογής σας

Οι προσεκτικοί αναγνώστες θα αναρρωτηθούν: Αφού η ρύθμιση (λίστα) DIRS είναι κενή αρχικά, πως ξέρει το Django που να βρει τα προεπιλεγμένα admin templates; Η απάντηση έχει ως εξής: εφόσον η ρύθμιση (boolean) APP_DIRS έχει την τιμή True, το Django αυτόματα κοιτάζει στο φάκελο templates/ κάθε εφαρμογής (που συμπεριλαμβάνεται στη ρύθμιση-λίστα INSTALLED_APPS), για τη χρήση τους ως fallback (μην ξεχνάτε ότι το django.contrib.admin είναι και αυτό μια εφαρμογή).

Η εφαρμογή ψηφοφορίας μας δεν είναι πολύ περίπλοκη και δεν χρειάζεται κάποια μεγάλη παραμετροποίηση των admin templates. Αλλά αν αναπτυχθεί και μεγαλώσει σε τέτοιο βαθμό που να χρειάζεται απαραιτήτως διάφορες λειτουργικές επεμβάσεις στα default templates του Django, τότε θα ήταν πιο λογικό να γίνει σε επίπεδο application (μέσα στο φάκελο templates της εφαρμογής σας) παρά σε επίπεδο project (μέσα στο φάκελο templates του project σας). Με αυτό τον τρόπο, θα μπορέσετε να συμπεριλάβετε την εφαρμογή ψηφοφορίας σας σε κάποιο μελλοντικό project και θα είστε σίγουροι ότι τα templates αυτής της εφαρμογής θα εφαρμοστούν αμέσως στο νέο project.

Δείτε στο εγχειρίδιο (documentation) φόρτωσης των templates για περισσότερες πληροφορίες σχετικά με το πως το Django βρίσκει-αναζητά τα templates.

Παραμετροποιώντας την αρχική σελίδα του Django admin

Ομοίως, ίσως να θέλετε να παραμετροποιήσετε (να φέρετε στα μέτρα σας) την εμφάνιση της αρχικής σελίδας του Django admin.

Από προεπιλογή, εμφανίζονται όλες οι εφαρμογές (κατά αλφαβητική σειρά) που συμπεριλαμβάνονται στη ρύθμιση (λίστα) INSTALLED_APPS και έχουν γίνει register με το admin. Αν θέλετε να κάνετε σημαντικές αλλαγές στην εμφάνιση της αρχικής σελίδας δεν έχετε παρά να βάλετε τη φαντασία σας να δουλέψει. Είναι γνωστό ότι η εμφάνιση της αρχικής σελίδας του admin είναι η πιο σημαντική και θα πρέπει να είναι εύκολο να την παραμετροποιήσετε.

To template προς παραμετροποίηση είναι το admin/index.html (κάντε το ίδιο όπως κάνατε για το αρχείο admin/base_site.html πριν – αντιγράψτε το από τον πηγαίο κώδικα του Django στον τοπικό φάκελο templates της εφαρμογής σας). Κατά τη διάρκεια επεξεργασίας του αρχείου θα δείτε ότι χρησιμοποιείται μια template variable με το όνομα app_list. Αυτή η μεταβλητή περιέχει κάθε εγκατεστημένη εφαρμογή στο Django (είναι μέσα στο INSTALLED_APPS και register στο admin). Αντί αυτού, μπορείτε να γράψετε hard-code συνδέσμους σε object-specific admin σελίδες με όποιον τρόπο πιστεύετε ότι είναι καλύτερος.

When you’re comfortable with the admin, read part 8 of this tutorial to learn how to use third-party packages.

Back to Top