{"title":"Παραμετροποιήσιμα Lookups","version":"3.0","locale":"el","docname":"howto/custom-lookups","url":"/el/3.0/howto/custom-lookups/","canonical":"https://djangodocs.dev/el/3.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/3.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/3.0/ref/models/lookups/\"><span class=\"doc\">Lookup API reference</span></a>.</p>\n<section id=\"a-lookup-example\">\n<h2>A lookup example<a class=\"heading-anchor\" href=\"#a-lookup-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Let’s start with a small custom lookup. We will write a custom lookup <code class=\"docutils literal notranslate\">ne</code>\nwhich works opposite to <code class=\"docutils literal notranslate\">exact</code>. <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code>\nwill translate to the SQL:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"ss\">&quot;author&quot;</span><span class=\"p\">.</span><span class=\"ss\">&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>There are two steps to making this work. Firstly we need to implement the\nlookup, then we need to tell Django about it:</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>To register the <code class=\"docutils literal notranslate\">NotEqual</code> lookup we will need to call <code class=\"docutils literal notranslate\">register_lookup</code> on\nthe field class we want the lookup to be available for. In this case, the lookup\nmakes sense on all <code class=\"docutils literal notranslate\">Field</code> subclasses, so we register it with <code class=\"docutils literal notranslate\">Field</code>\ndirectly:</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/3.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-transformer-example\">\n<h2>A transformer example<a class=\"heading-anchor\" href=\"#a-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>We can now run the queries we had before.\n<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code> will generate the following SQL:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">...</span> <span class=\"k\">WHERE</span> <span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span> <span class=\"o\">=</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>By using <code class=\"docutils literal notranslate\">Transform</code> instead of <code class=\"docutils literal notranslate\">Lookup</code> it means we are able to chain\nfurther lookups afterwards. So\n<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> will generate the following\nSQL:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">...</span> <span class=\"k\">WHERE</span> <span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&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>This also allows the result to be used in <code class=\"docutils literal notranslate\">ORDER BY</code> and <code class=\"docutils literal notranslate\">DISTINCT ON</code>\nclauses. For example <code class=\"docutils literal notranslate\">Experiment.objects.order_by('change__abs')</code> generates:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">...</span> <span class=\"k\">ORDER</span> <span class=\"k\">BY</span> <span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span> <span class=\"k\">ASC</span>\n</code></pre></div>\n<p>And on databases that support distinct on fields (such as PostgreSQL),\n<code class=\"docutils literal notranslate\">Experiment.objects.distinct('change__abs')</code> generates:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">...</span> <span class=\"k\">DISTINCT</span> <span class=\"k\">ON</span> <span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\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>So we would like <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> to generate\nthe following SQL:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">..</span> <span class=\"k\">WHERE</span> <span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span> <span class=\"o\">&lt;</span> <span class=\"mi\">27</span> <span class=\"k\">AND</span> <span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&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> και χρησιμοποιεί την αρχική τιμή του <code class=\"docutils literal notranslate\">lhs</code> (το <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>Let’s examine case-insensitive transformations here. This transformation isn’t\nvery useful in practice as Django already comes with a bunch of built-in\ncase-insensitive lookups, but it will be a nice demonstration of bilateral\ntransformations in a database-agnostic way.</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/3.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>Now, the queryset <code class=\"docutils literal notranslate\">Author.objects.filter(name__upper=&quot;doe&quot;)</code> will generate a case\ninsensitive query like this:</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">...</span> <span class=\"k\">WHERE</span> <span class=\"k\">UPPER</span><span class=\"p\">(</span><span class=\"ss\">&quot;author&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;name&quot;</span><span class=\"p\">)</span> <span class=\"o\">=</span> <span class=\"k\">UPPER</span><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> <span class=\"o\">**</span>extra_context<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":"A lookup example","anchor":"a-lookup-example","children":[]},{"title":"A transformer example","anchor":"a-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/3.0/howto/"}],"prev":{"docname":"howto/custom-model-fields","title":"Γράφοντας δικά σας πεδία μοντέλων","url":"/el/3.0/howto/custom-model-fields/"},"next":{"docname":"howto/custom-template-tags","title":"Γράφοντας δικά σας template tags και φίλτρα","url":"/el/3.0/howto/custom-template-tags/"},"formats":{"html":"/el/3.0/howto/custom-lookups/","markdown":"/el/3.0/howto/custom-lookups.md","json":"/el/3.0/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/el/3.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"]}