{"title":"Παραμετροποιήσιμα Lookups","version":"2.0","locale":"el","docname":"howto/custom-lookups","url":"/el/2.0/howto/custom-lookups/","canonical":"https://djangodocs.dev/el/2.0/howto/custom-lookups/","summary":"Το Django προσφέρει μια μεγάλη ποικιλία από προεγκατεστημένα lookups για το φιλτράρισμα (π.χ exact και icontains) των δεδομένων σας από την βάση δεδομένων.","html":"<h1>Παραμετροποιήσιμα Lookups<a class=\"heading-anchor\" href=\"#custom-lookups\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Το Django προσφέρει μια μεγάλη ποικιλία από <a class=\"reference internal\" href=\"/el/2.0/ref/models/querysets/#field-lookups\"><span class=\"std std-ref\">προεγκατεστημένα lookups</span></a> για το φιλτράρισμα (π.χ <code class=\"docutils literal notranslate\">exact</code> και <code class=\"docutils literal notranslate\">icontains</code>) των δεδομένων σας από την βάση δεδομένων. Το παρών εγχειρίδιο εξηγεί πως να γράψετε δικά σας lookups και πως να αλλάξετε τη συμπεριφορά των ήδη υπαρχουσών lookups. Για την σχετική αναφορά στο API των lookups, δείτε στο άρθρο <a class=\"reference internal\" href=\"/el/2.0/ref/models/lookups/\"><span class=\"doc\">Lookup API reference</span></a>.</p>\n<section id=\"a-simple-lookup-example\">\n<h2>Ένα απλό lookup παράδειγμα<a class=\"heading-anchor\" href=\"#a-simple-lookup-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ας ξεκινήσουμε με ένα απλό παραμετροποιήσιμο lookup. Θα γράψουμε ένα δικό μας lookup και θα του δώσουμε το όνομα <code class=\"docutils literal notranslate\">ne</code> (από τις λέξεις not equal), το οποίο θα έχει την ανάποδη συμπεριφορά του <code class=\"docutils literal notranslate\">exact</code>. Για παράδειγμα, αν γράψουμε <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code>, τότε αυτό θα μεταφραστεί στην SQL ως:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"s2\">&quot;author&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;name&quot;</span> <span class=\"o\">&lt;&gt;</span> <span class=\"s1\">&#39;Jack&#39;</span>\n</code></pre></div>\n<p>Η παραπάνω εντολή SQL είναι ανεξάρτητη από τη βάση δεδομένων που χρησιμοποιείτε, οπότε δεν θα χρειαστεί να ανησυχούμε γι” αυτό. Όλες οι βάσεις καταλαβαίνουν αυτή τη σύνταξη.</p>\n<p>Υπάρχουν δύο βήματα που πρέπει να κάνουμε για να δουλέψει το ανωτέρω. Πρώτα, πρέπει να υλοποιήσουμε το lookup και μετά πρέπει να το αναφέρουμε στο Django. Η υλοποίηση είναι λίγο πολύ ευθέως κατανοητή:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Lookup\n\n<span class=\"k\">class</span> <span class=\"nc\">NotEqual</span><span class=\"p\">(</span>Lookup<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;ne&#39;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> compiler<span class=\"p\">,</span> connection<span class=\"p\">):</span>\n        lhs<span class=\"p\">,</span> lhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_lhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        rhs<span class=\"p\">,</span> rhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_rhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        params <span class=\"o\">=</span> lhs_params <span class=\"o\">+</span> rhs_params\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> &lt;&gt; </span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>lhs<span class=\"p\">,</span> rhs<span class=\"p\">),</span> params\n</code></pre></div>\n<p>Σε αυτό το σημείο απλώς έχουμε ορίσει μια κλάση. Τίποτε περισσότερο. Επόμενο βήμα είναι κάνουμε register το νέο μας <code class=\"docutils literal notranslate\">NotEqual</code> lookup με κάποιο πεδίο από τα Django μοντέλα ή με όλα. Θα χρειαστεί να καλέσουμε την <code class=\"docutils literal notranslate\">register_lookup</code> πάνω στο πεδίο που θέλουμε αυτό το lookup να είναι διαθέσιμο. Αυτό γίνεται, γιατί σε μερικές περιπτώσεις δεν θέλουμε να έχουμε διαθέσιμο (να φιλτράρουμε, αν θέλετε) το lookup μας σε όλα τα πεδία (πχ IntegerField, DateField κλπ). Αν φτιάξουμε ένα άλλο lookup που να ελέγχει, πχ το πρώτο γράμμα ενός string δεν θα ήταν λογικό να το συνδέσουμε με ένα DateTimeField. Στην προκειμένη περίπτωση, το lookup μπορεί να εφαρμοστεί σε όλων των ειδών τα <code class=\"docutils literal notranslate\">Field</code> subclasses, οπότε θα το κάνουμε register με το <code class=\"docutils literal notranslate\">Field</code> απ” ευθείας:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models.fields</span> <span class=\"kn\">import</span> Field\nField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>NotEqual<span class=\"p\">)</span>\n</code></pre></div>\n<p>Το registration του lookup μπορεί να γίνει και με τη χρήση ενός decorator ως εξής:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models.fields</span> <span class=\"kn\">import</span> Field\n\n<span class=\"nd\">@Field</span><span class=\"o\">.</span>register_lookup\n<span class=\"k\">class</span> <span class=\"nc\">NotEqualLookup</span><span class=\"p\">(</span>Lookup<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n</code></pre></div>\n<p>Τώρα μπορούμε να χρησιμοποιήσουμε το <code class=\"docutils literal notranslate\">foo__ne</code> για κάθε τύπο πεδίου του <code class=\"docutils literal notranslate\">foo</code>. Θα χρειαστεί να βεβαιωθείτε ότι το registration του lookup, γίνεται πριν προσπαθήσετε να δημιουργήσετε querysets χρησιμοποιώντας το. Θα μπορούσατε να τοποθετήσετε τον παραπάνω κώδικα μέσα στο αρχείο <code class=\"docutils literal notranslate\">models.py</code> ή να κάνετε register το lookup μέσα στη μέθοδο <code class=\"docutils literal notranslate\">ready()</code> στο αντίστοιχο <code class=\"docutils literal notranslate\">AppConfig</code> της εφαρμογής σας.</p>\n<p>Ρίχνοντας μια πιο προσεκτική ματιά στην υλοποίηση αυτού του lookup, το πρώτο απαραίτητο attribute που χρειάζεται είναι το <code class=\"docutils literal notranslate\">lookup_name</code>. Αυτό επιτρέπει στο Django ORM να καταλάβει πως να μεταφράσει το <code class=\"docutils literal notranslate\">name__ne</code> και να χρησιμοποιήσει την κλάση <code class=\"docutils literal notranslate\">NotEqual</code> για να παράξει την SQL. Συμβατικά, αυτά τα ονόματα είναι πάντα πεζοί χαρακτήρες (μόνο γράμματα) και η μοναδική αυστηρή απαίτηση είναι να μην περιέχουν δύο συνεχόμενες κάτω παύλες, <code class=\"docutils literal notranslate\">__</code>.</p>\n<p>Έπειτα χρειάζεται να ορίσουμε την μέθοδο <code class=\"docutils literal notranslate\">as_sql</code>. Αυτή δέχεται ως όρισμα ένα <code class=\"docutils literal notranslate\">SQLCompiler</code> object, με το όνομα <code class=\"docutils literal notranslate\">compiler</code> και την ενεργή σύνδεση της βάσης δεδομένων με το όνομα <code class=\"docutils literal notranslate\">connection</code>. Τα <code class=\"docutils literal notranslate\">SQLCompiler</code> objects δεν βρίσκονται κάπου γραμμένα στο εγχειρίδιο του Django αλλά το μόνο πράγμα που χρειάζεται να ξέρετε γι” αυτά είναι ότι έχουν μια μέθοδο <code class=\"docutils literal notranslate\">compile()</code> η οποία επιστρέφει ένα tuple που περιέχει ένα SQL string και κάποιες παραμέτρους οι οποίες “γεμίζουν” αυτό το SQL string. Στις περισσότερες περιπτώσεις δεν θα χρειαστεί να την χρησιμοποιήσετε και μπορείτε να συνεχίσετε με τις μεθόδους <code class=\"docutils literal notranslate\">process_lhs()</code> και <code class=\"docutils literal notranslate\">process_rhs()</code>.</p>\n<p>Ένα <code class=\"docutils literal notranslate\">Lookup</code> συνεργάζεται με δύο τιμές, την <code class=\"docutils literal notranslate\">lhs</code> και την <code class=\"docutils literal notranslate\">rhs</code>, οι οποίες είναι σύντμηση των λέξεων left-hand side (αριστερό μέρος) και right-hand side (δεξί μέρος). Το αριστερό μέρος αναφέρεται συνήθως σε κάποιο πεδίο αλλά μπορεί να είναι οτιδήποτε αρκεί να έχει υλοποιήσει το <a class=\"reference internal\" href=\"/el/2.0/ref/models/lookups/#query-expression\"><span class=\"std std-ref\">API για εκφράσεις ερωτημάτων</span></a>. Το δεξί μέρος είναι η τιμή η οποία δίνεται από τον χρήστη. Στο παράδειγμα <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code>, το αριστερό μέρος αναφέρεται στο πεδίο <code class=\"docutils literal notranslate\">name</code> του μοντέλου <code class=\"docutils literal notranslate\">Author</code> και το string <code class=\"docutils literal notranslate\">'Jack'</code> αποτελεί το δεξί μέρος.</p>\n<p>Καλούμε την <code class=\"docutils literal notranslate\">process_lhs</code> και την <code class=\"docutils literal notranslate\">process_rhs</code> για να μετατρέψουμε το <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code> στις τιμές που χρειαζόμαστε για την SQL χρησιμοποιώντας το <code class=\"docutils literal notranslate\">compiler</code> object που περιγράψαμε παραπάνω. Αυτές οι μέθοδοι επιστρέφουν tuples που περιέχουν λίγη SQL και κάποιες παραμέτρους που θα “γεμίσουν” αυτή την SQL. Ότι ακριβώς χρειαζόμαστε για να επιστρέψει η μέθοδος <code class=\"docutils literal notranslate\">as_sql</code>. Στο παραπάνω παράδειγμα, η <code class=\"docutils literal notranslate\">process_lhs</code> επιστρέφει <code class=\"docutils literal notranslate\">('&quot;author&quot;.&quot;name&quot;', [])</code> και η <code class=\"docutils literal notranslate\">process_rhs</code> επιστρέφει <code class=\"docutils literal notranslate\">('&quot;%s&quot;', ['Jack'])</code>. Όπως θα είδατε, δεν υπάρχουν παράμετροι για το αριστερό μέρος, αλλά αυτό εξαρτάται από την περίπτωση. Όπως και να έχει πάντως, θα πρέπει πάντα να περιλαμβάνονται στο τελικό tuple προς επιστροφή (η μεταβλητή <code class=\"docutils literal notranslate\">params</code> στην <code class=\"docutils literal notranslate\">as_sql</code>).</p>\n<p>Στο τέλος ενώνουμε τα μέρη σε μια SQL εντολή με τη χρήση του <code class=\"docutils literal notranslate\">&lt;&gt;</code> και παρέχουμε όλες τις παραμέτρους για το query (ερώτημα). Αυτό που επιστρέφουμε είναι ένα tuple που περιέχει την παραγόμενη SQL εντολή και τις παραμέτρους, κενές ή όχι. Το tuple που θα επιστραφεί, αναφερόμενοι στην ανωτέρω <code class=\"docutils literal notranslate\">as_sql</code>, είναι το <code class=\"docutils literal notranslate\">('&quot;author&quot;.&quot;name&quot; &lt;&gt; &quot;%s&quot;', ['Jack'])</code>.</p>\n</section>\n<section id=\"a-simple-transformer-example\">\n<h2>Ένα απλό παράδειγμα transformer<a class=\"heading-anchor\" href=\"#a-simple-transformer-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Το παραπάνω lookup που φτιάξαμε είναι ωραίο, αλλά σε αρκετές περιπτώσεις θα θέλετε να έχετε τη δυνατότητα να ενώνετε τα lookups μεταξύ τους. Για παράδειγμα, ας υποθέσουμε ότι χτίζουμε μια εφαρμογή όπου θέλουμε να κάνουμε χρήση της μεθόδου <code class=\"docutils literal notranslate\">abs()</code>, που επιστρέφει το απόλυτο ενός αριθμού. Έχουμε ένα μοντέλο με το όνομα <code class=\"docutils literal notranslate\">Experiment</code> το οποίο καταγράφει μια τιμή έναρξης (start), μια τέλους (end) και την αλλαγή (αρχή – τέλος). Θα θέλαμε να βρούμε όλα τα πειράματα (experiments) όπου η αλλαγή ήταν ίση με μια συγκεκριμένη τιμή (<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code>) ή η αλλαγή ήταν μικρότερη ή ίση μιας συγκεκριμένης τιμής (<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code>). Εδώ βλέπετε τη σύνδεση μεταξύ των lookups που αναφέραμε πριν (<code class=\"docutils literal notranslate\">abs__lt</code>).</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>Αυτό το παράδειγμα είναι λίγο πολύ σκηνοθετημένο αλλά επιδεικνύει όμορφα τις  λειτουργίες που είναι δυνατόν να υλοποιηθούν χωρίς την εξάρτηση πάνω σε μια συγκεκριμένη βάση δεδομένων και χωρίς να ξαναγράφουμε κώδικα που υπάρχει ήδη στο Django.</p>\n</aside>\n<p>We will start by writing an <code class=\"docutils literal notranslate\">AbsoluteValue</code> transformer. This will use the SQL\nfunction <code class=\"docutils literal notranslate\">ABS()</code> to transform the value before comparison:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Transform\n\n<span class=\"k\">class</span> <span class=\"nc\">AbsoluteValue</span><span class=\"p\">(</span>Transform<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;abs&#39;</span>\n    function <span class=\"o\">=</span> <span class=\"s1\">&#39;ABS&#39;</span>\n</code></pre></div>\n<p>Επόμενο βήμα είναι κάνουμε register την κλάση μας με το πεδίο <code class=\"docutils literal notranslate\">IntegerField</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> IntegerField\nIntegerField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>AbsoluteValue<span class=\"p\">)</span>\n</code></pre></div>\n<p>Μπορούμε τώρα να τρέξουμε τα queries στα οποία αναφερθήκαμε παραπάνω. Το <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code> θα παράξει την ακόλουθη SQL εντολή:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>SELECT <span class=\"o\">...</span> WHERE ABS<span class=\"p\">(</span><span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span><span class=\"p\">)</span> <span class=\"o\">=</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>Χρησιμοποιώντας την <code class=\"docutils literal notranslate\">Transform</code> αντί της <code class=\"docutils literal notranslate\">Lookup</code> μας επιτρέπει να συνδέουμε περαιτέρω lookups στην αλυσίδα. Επομένως το <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> θα παράξει την ακόλουθη SQL εντολή:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>SELECT <span class=\"o\">...</span> WHERE ABS<span class=\"p\">(</span><span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span><span class=\"p\">)</span> <span class=\"o\">&lt;</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>Σημειώστε ότι στην περίπτωση που δεν υπάρχει άλλο lookup στο τέλος, το Django μεταφράζει το <code class=\"docutils literal notranslate\">change__abs=27</code> ως <code class=\"docutils literal notranslate\">change__abs__exact=27</code>.</p>\n<p>Για να βρει το Django τον τύπο των lookups που επιτρέπονται μετά το δικό μας (<code class=\"docutils literal notranslate\">AbsoluteValue</code>), κοιτάζει το attribute <code class=\"docutils literal notranslate\">output_field</code> το οποίο δεν χρειάστηκε να το ορίσουμε στο συγκεκριμένο παράδειγμα γιατί έτυχε ο αριθμός που συγκρίνουμε, στο δεξί μέρος, να είναι ακέραιος (27). Αν μπερδευτήκατε, ας το ξεκαθαρίσουμε: Η <code class=\"docutils literal notranslate\">Transform</code> προσφέρει τη μετατροπή ενός πεδίου (πχ του <code class=\"docutils literal notranslate\">change</code>) σε κάποια άλλη τιμή (πχ από -27 που μπορεί να ήταν, σε 27) προτού συγκριθεί με το δεξί μέρος και γίνει το lookup στη βάση δεδομένων. Ο τύπος της νέας αυτής τιμής (πχ 27 αντί -27) δηλώνεται στο <code class=\"docutils literal notranslate\">output_field</code> του δικού μας <code class=\"docutils literal notranslate\">AbsoluteValue ``. Δεν το δηλώσαμε γιατί και οι δύο τιμές είναι τύπου int. Αν υποθέσουμε όμως ότι έχουμε πιο περίπλοκα πεδία (πχ καρτεσιανές συντεταγμένες ή μιγαδικούς αριθμούς) τότε ίσως θα θέλαμε να προσδιορίσουμε τον τύπο της νέας τιμής ως ``FloatField</code> για περαιτέρω lookups. Αυτό μπορεί να γίνει θέτοντας το attribute `` output_field`` ως property της δικής μας κλάσης, ως εξής:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> FloatField<span class=\"p\">,</span> Transform\n\n<span class=\"k\">class</span> <span class=\"nc\">AbsoluteValue</span><span class=\"p\">(</span>Transform<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;abs&#39;</span>\n    function <span class=\"o\">=</span> <span class=\"s1\">&#39;ABS&#39;</span>\n\n    <span class=\"nd\">@property</span>\n    <span class=\"k\">def</span> <span class=\"nf\">output_field</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> FloatField<span class=\"p\">()</span>\n</code></pre></div>\n<p>Με αυτό τον τρόπο είμαστε σίγουροι ότι το δικό μας transformation θα επιστρέψει μια τιμή τύπου float και τα επόμενα lookups (αν υπάρχουν, πχ το lte στο <code class=\"docutils literal notranslate\">abs__lte</code>) θα “δουν” την τιμή αυτή ως float και όχι ως int όπως ήταν στην αρχή. Ένα άλλο πολύ κοινό παράδειγμα της <code class=\"docutils literal notranslate\">Transform</code> είναι η μετατροπή ενός <code class=\"docutils literal notranslate\">DateField</code> στην τιμή του έτους μόνο. Για παράδειγμα, θα θέλατε να δείτε ποια πειράματα έγιναν το έτος 2016. Θα θέλατε να το γράψετε ως εξής: <code class=\"docutils literal notranslate\">Experiment.objects.filter(date__year=2016)</code>. Το <code class=\"docutils literal notranslate\">date</code> είναι το πεδίο του μοντέλου μας, τύπου <code class=\"docutils literal notranslate\">DateField</code> και το <code class=\"docutils literal notranslate\">year</code> το lookup (που υπάρχει ήδη μέσα στο Django). Το <code class=\"docutils literal notranslate\">year</code> lookup “ξηλώνει” μόνο το έτος από την ημερομηνία και το συγκρίνει με το 2016. Έτσι, μετατρέπεται η ημερομηνία (<code class=\"docutils literal notranslate\">DateField</code>) σε έτος (<code class=\"docutils literal notranslate\">IntegerField</code>) και συγκρίνεται με το δεξί μέρος.</p>\n</section>\n<section id=\"writing-an-efficient-abs-lt-lookup\">\n<h2>Γράφοντας ένα πιο αποτελεσματικό <code class=\"docutils literal notranslate\">abs__lt</code> lookup<a class=\"heading-anchor\" href=\"#writing-an-efficient-abs-lt-lookup\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Όταν χρησιμοποιούμε το παραπάνω <code class=\"docutils literal notranslate\">abs</code> lookup, η παραγόμενη SQL, σε μερικές περιπτώσεις, δεν χρησιμοποιεί αποτελεσματικά τα ευρετήρια (indexes) της βάσης δεδομένων. Πιο συγκεκριμένα, όταν χρησιμοποιούμε το <code class=\"docutils literal notranslate\">change__abs__lt=27</code>, αυτό είναι ισοδύναμο με το <code class=\"docutils literal notranslate\">change__gt=-27</code> AND <code class=\"docutils literal notranslate\">change__lt=27</code>. (Στη περίπτωση του <code class=\"docutils literal notranslate\">lte</code> θα μπορούσαμε να χρησιμοποιήσουμε την εντολή SQL <code class=\"docutils literal notranslate\">BETWEEN</code>).</p>\n<p>Θα θέλαμε, επομένως, η παραγόμενη SQL από το <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> να δείχνει κάπως έτσι:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>SELECT <span class=\"o\">..</span> WHERE <span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span> <span class=\"o\">&lt;</span> <span class=\"mi\">27</span> AND <span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span> <span class=\"o\">&gt;</span> <span class=\"o\">-</span><span class=\"mi\">27</span>\n</code></pre></div>\n<p>Η υλοποίηση αυτού φαίνεται παρακάτω:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Lookup\n\n<span class=\"k\">class</span> <span class=\"nc\">AbsoluteValueLessThan</span><span class=\"p\">(</span>Lookup<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;lt&#39;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> compiler<span class=\"p\">,</span> connection<span class=\"p\">):</span>\n        lhs<span class=\"p\">,</span> lhs_params <span class=\"o\">=</span> compiler<span class=\"o\">.</span>compile<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>lhs<span class=\"o\">.</span>lhs<span class=\"p\">)</span>\n        rhs<span class=\"p\">,</span> rhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_rhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        params <span class=\"o\">=</span> lhs_params <span class=\"o\">+</span> rhs_params <span class=\"o\">+</span> lhs_params <span class=\"o\">+</span> rhs_params\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> &lt; </span><span class=\"si\">%s</span><span class=\"s1\"> AND </span><span class=\"si\">%s</span><span class=\"s1\"> &gt; -</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>lhs<span class=\"p\">,</span> rhs<span class=\"p\">,</span> lhs<span class=\"p\">,</span> rhs<span class=\"p\">),</span> params\n\nAbsoluteValue<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>AbsoluteValueLessThan<span class=\"p\">)</span>\n</code></pre></div>\n<p>Υπάρχουν μερικά αξιοσημείωτα πράγματα εδώ. Πρώτα απ’ όλα το <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code> δεν καλεί τη μέθοδο <code class=\"docutils literal notranslate\">process_lhs()</code>. Αντιθέτως, υπερπηδά τη μετατροπή του <code class=\"docutils literal notranslate\">lhs</code> που γίνεται από την <code class=\"docutils literal notranslate\">AbsoluteValue</code> και χρησιμοποιεί την αρχική τιμή του lhs` (το <code class=\"docutils literal notranslate\">self.lhs</code> είναι η τιμή μετά την μετατροπή ενώ το <code class=\"docutils literal notranslate\">self.lhs.lhs</code> είναι η αρχική τιμή του <code class=\"docutils literal notranslate\">change</code>). Αυτό γίνεται γιατί θέλουμε να έχουμε το <code class=\"docutils literal notranslate\">&quot;experiments&quot;.&quot;change&quot;</code> και όχι το <code class=\"docutils literal notranslate\">ABS(&quot;experiments&quot;.&quot;change&quot;)</code>. Είναι ασφαλής η αναφορά μας απ’ ευθείας στο <code class=\"docutils literal notranslate\">self.lhs.lhs</code> γιατί η <code class=\"docutils literal notranslate\">Lookup</code> κλάση <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code> μπορεί να προσπελασθεί μόνο από την <code class=\"docutils literal notranslate\">Transform</code> κλάση <code class=\"docutils literal notranslate\">AbsoluteValue</code> (λόγω του register στην τελευταία γραμμή), δηλαδή το <code class=\"docutils literal notranslate\">lhs</code> θα είναι πάντα ένα instance της Transform κλάσης <code class=\"docutils literal notranslate\">AbsoluteValue</code>.</p>\n<p>Επισημαίνεται επίσης το γεγονός ότι όχι μόνο και τα δύο μέρη (αριστερό και δεξί) χρησιμοποιούνται πολλές φορές μέσα στο SQL query αλλά και οι παράμετροι επίσης (<code class=\"docutils literal notranslate\">lhs_params</code> και <code class=\"docutils literal notranslate\">rhs_params</code>).</p>\n<p>Ο λόγος που γίνεται αυτό είναι γιατί, σε περίπτωση που το <code class=\"docutils literal notranslate\">self.rhs</code> είναι κάτι διαφορετικό από έναν ακέραιο (πχ μια αναφορά σε ένα <code class=\"docutils literal notranslate\">F()</code>) δε θα μπορούμε να κάνουμε τις μετατροπές στην Python.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Σημείωση</p>\n<p>Στην πραγματικότητα, τα περισσότερα lookups που εμπεριέχουν το <code class=\"docutils literal notranslate\">__abs</code> θα μπορούσαν να υλοποιηθούν με την παραπάνω μέθοδο και στις περισσότερες βάσεις δεδομένων θα μπορέσετε να εκμεταλλευτείτε τη δυνατότητα των ευρετηρίων (indexes) τους. Ωστόσο, στην PostgreSQL ίσως θα θέλατε να προσθέσετε ένα ευρετήριο για το <code class=\"docutils literal notranslate\">abs(change)</code> το οποίο θα επιτρέψει σε αυτά τα queries να είναι πολύ αποτελεσματικά.</p>\n</aside>\n</section>\n<section id=\"a-bilateral-transformer-example\">\n<h2>Ένα παράδειγμα ενός διμερούς transformer<a class=\"heading-anchor\" href=\"#a-bilateral-transformer-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Το παράδειγμα της <code class=\"docutils literal notranslate\">Transformer</code> κλάσης <code class=\"docutils literal notranslate\">AbsoluteValue</code> που περιγράψαμε παραπάνω είναι μια μετατροπή η οποία εφαρμόζεται στο αριστερό μέρος του lookup (στο πεδίο <code class=\"docutils literal notranslate\">change</code>). Ίσως να υπάρξουν, μερικές περιπτώσεις όπου θα θέλατε η μετατροπή να εφαρμοστεί και στο αριστερό και στο δεξί μέρος. Για παράδειγμα, αν θέλετε να φιλτράρετε ένα queryset βασιζόμενο στην ισότητα των δύο μερών (αριστερό και δεξί) με την χρήση κάποιας SQL συνάρτησης.</p>\n<p>Ας εξετάσουμε την απλή περίπτωση μιας μετατροπής που δεν κάνει διάκριση μεταξύ πεζών και κεφαλαίων γραμμάτων. Αυτή η μετατροπή δεν είναι πολύ χρήσιμη στην πράξη καθώς το Django έχει προεγκατεστημένα αρκετά lookups που δεν κάνουν διακρίσεις μεταξύ πεζών-κεφαλαίων. Παρόλ’ αυτά αποτελεί ένα χρήσιμο παράδειγμα για την επίδειξη των διμερών μετατροπών (bilateral transformations) ανεξαρτήτως της βάση δεδομένων που χρησιμοποιείται.</p>\n<p>Ορίζουμε έναν transformer <code class=\"docutils literal notranslate\">UpperCase</code> ο οποίος χρησιμοποιεί την SQL συνάρτηση <code class=\"docutils literal notranslate\">UPPER()</code> για να μετατρέψει τις τιμές πριν την σύγκριση. Θέτουμε το attribute <a class=\"reference internal\" href=\"/el/2.0/ref/models/lookups/#django.db.models.Transform.bilateral\" title=\"django.db.models.Transform.bilateral\"><code class=\"xref py py-attr docutils literal notranslate\">bilateral = True</code></a> για να υποδείξουμε ότι η μετατροπή θα πρέπει να γίνει όχι μόνο στο αριστερό μέρος, <code class=\"docutils literal notranslate\">lhs</code>, αλλά και στο δεξί, <code class=\"docutils literal notranslate\">rhs</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Transform\n\n<span class=\"k\">class</span> <span class=\"nc\">UpperCase</span><span class=\"p\">(</span>Transform<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;upper&#39;</span>\n    function <span class=\"o\">=</span> <span class=\"s1\">&#39;UPPER&#39;</span>\n    bilateral <span class=\"o\">=</span> <span class=\"kc\">True</span>\n</code></pre></div>\n<p>Έπειτα το κάνουμε register με τους ανάλογους τύπους πεδίων:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> CharField<span class=\"p\">,</span> TextField\nCharField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>UpperCase<span class=\"p\">)</span>\nTextField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>UpperCase<span class=\"p\">)</span>\n</code></pre></div>\n<p>Τώρα το queryset <code class=\"docutils literal notranslate\">Author.objects.filter(name__upper=&quot;doe&quot;)</code> θα παράξει ένα query το οποίο δεν θα κάνει διάκριση μεταξύ πεζών-κεφαλαίων γραμμάτων:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>SELECT <span class=\"o\">...</span> WHERE UPPER<span class=\"p\">(</span><span class=\"s2\">&quot;author&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">)</span> <span class=\"o\">=</span> UPPER<span class=\"p\">(</span><span class=\"s1\">&#39;doe&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"writing-alternative-implementations-for-existing-lookups\">\n<h2>Γράφοντας εναλλακτικές υλοποιήσεις για ήδη υπάρχοντα lookups<a class=\"heading-anchor\" href=\"#writing-alternative-implementations-for-existing-lookups\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Κάποιες φορές, μερικές βάσεις δεδομένων απαιτούν έναν διαφορετικό τρόπο γραφής της SQL για την ίδια λειτουργία. Για παράδειγμα, κάποιες βάσεις για να προσδιορίσουν τη λογική «όχι ίσο με», αντί του συμβόλου <code class=\"docutils literal notranslate\">&lt;&gt;</code> απαιτούν το <code class=\"docutils literal notranslate\">!=</code>. (Στην πραγματικότητα σχεδόν όλες οι βάσεις δεδομένων υποστηρίζουν και τα δύο αυτά σύμβολα, συμπεριλαμβανομένων και όλων των επίσημων βάσεων δεδομένων που υποστηρίζει το Django). Σε αυτό το παράδειγμα θα ξαναγράψουμε μια δικιά μας υλοποίηση, για την MySQL, της λειτουργίας NotEqual.</p>\n<p>We can change the behavior on a specific backend by creating a subclass of\n<code class=\"docutils literal notranslate\">NotEqual</code> with an <code class=\"docutils literal notranslate\">as_mysql</code> method:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">MySQLNotEqual</span><span class=\"p\">(</span>NotEqual<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">as_mysql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> compiler<span class=\"p\">,</span> connection<span class=\"p\">):</span>\n        lhs<span class=\"p\">,</span> lhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_lhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        rhs<span class=\"p\">,</span> rhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_rhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        params <span class=\"o\">=</span> lhs_params <span class=\"o\">+</span> rhs_params\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> != </span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>lhs<span class=\"p\">,</span> rhs<span class=\"p\">),</span> params\n\nField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>MySQLNotEqual<span class=\"p\">)</span>\n</code></pre></div>\n<p>Μπορούμε, έπειτα, να κάνουμε register την κλάση αυτή με το <code class=\"docutils literal notranslate\">Field</code>. Η κλάση <code class=\"docutils literal notranslate\">MySQLNotEqual</code> αντικαθιστά την κλάση <code class=\"docutils literal notranslate\">NotEqual</code>, μόνο για τις MySQL βάσεις δεδομένων, αφού μοιράζονται το ίδιο <code class=\"docutils literal notranslate\">lookup_name</code>.</p>\n<p>Κατά τη διάρκεια μετάφρασης του query, το Django ψάχνει για τις μεθόδους``as_%s % connection.vendor`` και αν δεν βρει κάποια τότε χρησιμοποιεί την <code class=\"docutils literal notranslate\">as_sql</code>. Τα ονόματα των vendor για τις προεγκατεστημένες στο Django database backends είναι τα <code class=\"docutils literal notranslate\">sqlite</code>, <code class=\"docutils literal notranslate\">postgresql</code>, <code class=\"docutils literal notranslate\">oracle</code> και <code class=\"docutils literal notranslate\">mysql</code>.</p>\n</section>\n<section id=\"how-django-determines-the-lookups-and-transforms-which-are-used\">\n<h2>Πως προσδιορίζει το Django τα lookups και τα transforms που χρησιμοποιούνται<a class=\"heading-anchor\" href=\"#how-django-determines-the-lookups-and-transforms-which-are-used\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Σε μερικές περιπτώσεις θα θέλατε να αλλάξετε, δυναμικά, το <code class=\"docutils literal notranslate\">Transform</code> ή το <code class=\"docutils literal notranslate\">Lookup</code> που επιστρέφεται ανάλογα το όνομα που δίνεται στο query παρά να μπείτε στη διαδικασία να φτιάξετε ένα για το καθένα. Θα μπορούσατε, για παράδειγμα, να έχετε ένα πεδίο το οποίο αποθηκεύει συντεταγμένες ή κάποια αυθαίρετη διάσταση και θέλετε να μπορείτε να γράφετε το <code class=\"docutils literal notranslate\">.filter(coords__x7=4)</code> και να σας επιστρέφει τα objects όπου η 7η συντεταγμένη έχει την τιμή 4. Για να το κάνετε αυτό, θα πρέπει να παρακάμψετε (override) την <code class=\"docutils literal notranslate\">get_lookup</code> με κάτι σαν αυτό:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"nc\">CoordinatesField</span><span class=\"p\">(</span>Field<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">get_lookup</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> lookup_name<span class=\"p\">):</span>\n        <span class=\"k\">if</span> lookup_name<span class=\"o\">.</span>startswith<span class=\"p\">(</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">):</span>\n            <span class=\"k\">try</span><span class=\"p\">:</span>\n                dimension <span class=\"o\">=</span> <span class=\"nb\">int</span><span class=\"p\">(</span>lookup_name<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:])</span>\n            <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n                <span class=\"k\">pass</span>\n            <span class=\"k\">else</span><span class=\"p\">:</span>\n                <span class=\"k\">return</span> get_coordinate_lookup<span class=\"p\">(</span>dimension<span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>get_lookup<span class=\"p\">(</span>lookup_name<span class=\"p\">)</span>\n</code></pre></div>\n<p>Μετά θα ορίσετε τη μέθοδο <code class=\"docutils literal notranslate\">get_coordinate_lookup</code>, καταλλήλως, για να επιστρέφει μια subclass της <code class=\"docutils literal notranslate\">Lookup</code> η οποία θα χειριστεί την σχετική τιμή της μεταβλητής <code class=\"docutils literal notranslate\">dimension</code>.</p>\n<p>Ομοίως, υπάρχει μια μέθοδος για την <code class=\"docutils literal notranslate\">Transform</code> με το όνομα <code class=\"docutils literal notranslate\">get_transform()</code>. Η μέθοδος <code class=\"docutils literal notranslate\">get_lookup()</code> θα πρέπει πάντα να επιστρέφει μια subclass της <code class=\"docutils literal notranslate\">Lookup</code> ενώ η <code class=\"docutils literal notranslate\">get_transform()</code> μια subclass της <code class=\"docutils literal notranslate\">Transform</code>. Είναι σημαντικό να θυμάστε ότι τα objects της κλάσης <code class=\"docutils literal notranslate\">Transform</code> μπορούν να φιλτραριστούν περαιτέρω ενώ τα objects της κλάσης <code class=\"docutils literal notranslate\">Lookup</code> όχι.</p>\n<p>Όταν φιλτράρετε και έχει απομείνει μόνο ένα lookup όνομα, το Django ψάξει για κάποιο <code class=\"docutils literal notranslate\">Lookup</code>. Αν υπάρχουν πολλά τότε θα ψάξει για κάποιο <code class=\"docutils literal notranslate\">Transform</code>. Στην περίπτωση που υπάρχει μόνο ένα όνομα και δεν βρεθεί κάποιο <code class=\"docutils literal notranslate\">Lookup</code>, τότε το Django θα ψάξει για ένα <code class=\"docutils literal notranslate\">Transform</code> και μετά το <code class=\"docutils literal notranslate\">exact</code> lookup πάνω σε αυτό το <code class=\"docutils literal notranslate\">Transform</code>. Στο τέλος, το Django, πάντα θα ψάχνει για ένα <code class=\"docutils literal notranslate\">Lookup</code>. Για να ξεκαθαρίσουμε λίγο το τοπίο:</p>\n<ul class=\"simple\">\n<li><p>Το <code class=\"docutils literal notranslate\">.filter(myfield__mylookup)</code> θα καλέσει την μέθοδο <code class=\"docutils literal notranslate\">myfield.get_lookup('mylookup')</code>.</p></li>\n<li><p>Το <code class=\"docutils literal notranslate\">.filter(myfield__mytransform__mylookup)</code> θα καλέσει τη μέθοδο <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code> και μετά την <code class=\"docutils literal notranslate\">mytransform.get_lookup('mylookup')</code>.</p></li>\n<li><p>Το <code class=\"docutils literal notranslate\">.filter(myfield__mytransform)</code> θα καλέσει πρώτα τη μέθοδο <code class=\"docutils literal notranslate\">myfield.get_lookup('mytransform')</code>, η οποία θα αποτύχει. Έπειτα θα καλέσει την μέθοδο <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code> και τέλος την <code class=\"docutils literal notranslate\">mytransform.get_lookup('exact')</code>.</p></li>\n</ul>\n</section>","rootId":"custom-lookups","toc":[{"title":"Ένα απλό lookup παράδειγμα","anchor":"a-simple-lookup-example","children":[]},{"title":"Ένα απλό παράδειγμα transformer","anchor":"a-simple-transformer-example","children":[]},{"title":"Γράφοντας ένα πιο αποτελεσματικό abs__lt lookup","anchor":"writing-an-efficient-abs-lt-lookup","children":[]},{"title":"Ένα παράδειγμα ενός διμερούς transformer","anchor":"a-bilateral-transformer-example","children":[]},{"title":"Γράφοντας εναλλακτικές υλοποιήσεις για ήδη υπάρχοντα lookups","anchor":"writing-alternative-implementations-for-existing-lookups","children":[]},{"title":"Πως προσδιορίζει το Django τα lookups και τα transforms που χρησιμοποιούνται","anchor":"how-django-determines-the-lookups-and-transforms-which-are-used","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"Οδηγοί «Πως-να»","url":"/el/2.0/howto/"}],"prev":{"docname":"howto/custom-model-fields","title":"Γράφοντας δικά σας πεδία μοντέλων","url":"/el/2.0/howto/custom-model-fields/"},"next":{"docname":"howto/custom-template-tags","title":"Γράφοντας δικά σας template tags και φίλτρα","url":"/el/2.0/howto/custom-template-tags/"},"formats":{"html":"/el/2.0/howto/custom-lookups/","markdown":"/el/2.0/howto/custom-lookups.md","json":"/el/2.0/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/2.0.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/el/2.0/howto/custom-lookups/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}