---
title: "Conas cuardaigh saincheaptha a scríobh"
version: 6.1
locale: ga
source: https://docs.djangoproject.com/ga/6.1/howto/custom-lookups/
canonical: https://djangodocs.dev/ga/6.1/howto/custom-lookups/
---
# Conas cuardaigh saincheaptha a scríobh

Cuireann Django \<field-lookups\>réimse leathan de: ref: cuardaigh ionsuite \`ar fáil le haghaidh scagadh (mar shampla, \`\`cruth\` agus icontains\`). Míníonn an doiciméadú seo conas cuardaigh saincheaptha a scríobh agus conas obair na gcuardaigh atá ann cheana a athrú. Le haghaidh tagairtí API de chuardaigh, féach an:doc: /ref/models/lookups.

## Sampla cuardaigh

Tosaímid le cuardach beag saincheaptha. Scríobhfaimid cuardach saincheaptha `ne` a oibríonn os coinne cruinn \`. Aistreoidh Author.Objects.Filter (name\_\_ne='Jack') go dtí an SQL:

```sql
"author"."name" <> 'Jack'
```

Tá an SQL seo neamhspleách ar chúltaca, mar sin ní gá dúinn a bheith buartha faoi bhunachair sonraí éagsúla.

Tá dhá chéim ann chun an obair seo a dhéanamh. Ar dtús ní mór dúinn an cuardach a chur i bhfeidhm, ansin ní mór dúinn a insint do Django faoi:

```
from django.db.models import Lookup

class NotEqual(Lookup):
    lookup_name = "ne"

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return "%s <> %s" % (lhs, rhs), params
```

Chun an cuardach `NoteQual` a chlárú beidh orainn glaoch ar register\_lookup\` ar an rang réimse a theastaíonn uainn go mbeadh an cuardach ar fáil dó. Sa chás seo, bíonn ciall ag an cuardach ar gach fo-aicme Field\`, mar sin cláraímid é le Field\` go díreach:

```
from django.db.models import Field

Field.register_lookup(NotEqual)
```

Is féidir clárú cuardaigh a dhéanamh freisin ag baint úsáide as patrún maisitheora:

```
from django.db.models import Field

@Field.register_lookup
class NotEqualLookup(Lookup): ...
```

Is féidir linn `foo__ne` a úsáid anois le haghaidh aon réimse `foo`. Beidh ort a chinntiú go dtarlaíonn an clárú seo sula ndéanann tú iarracht aon cheisteanna a chruthú ag baint úsáide as. D'fhéadfá an cur i bhfeidhm a chur i gcomhad ```models.py`, nó an cuardach a chlárú sa mhodh ``ready () ``de `AppConfig```.

Ag breathnú níos dlúithe ar an gcur i bhfeidhm, is é lookup\_name\` an chéad tréith riachtanach. Ligeann sé seo don ORM tuiscint a fháil ar conas `name__ne` a léirmhíniú agus `NoteQual` a úsáid chun an SQL a ghiniúint. De réir choinbhinsiúin, is teaghráin bheaga iad na hainmneacha seo i gcónaí nach bhfuil ach litreacha ann, ach is é an t-aon cheanglas crua ná nach gcaithfidh an teaghrán `__` a bheith ann.

We then need to define the `as_sql` method. This takes a `SQLCompiler`
object, called `compiler`, and the active database connection.
`SQLCompiler` objects are not documented, but the only thing we need to know
about them is that they have a `compile()` method which returns a tuple
containing an SQL string, and the parameters to be interpolated into that
string. In most cases, you don't need to use it directly and can pass it on to
`process_lhs()` and `process_rhs()`.

Oibríonn `Lookup` i gcoinne dhá luach, lhs\` agus `rhs`, ag seasamh ar thaobh na láimhe clé agus ar dheis. \<query-expression\>Is tagairt réimse é an taobh na láimhe clé de ghnáth, ach is féidir é a bheith ina rud ar bith a chur i bhfeidhm an:ref: abairt fiosraithe API \`. Is é an lámh dheis an luach a thugann an t-úsáideoir. Sa sampla \`\`Author.Objects.Filter (name\_\_ne='Jack') \`, is tagairt é an taobh clé don réimse `ainm` den tsamhail ```Author ``, agus ``Jack'``` is é an taobh na láimhe deise.

Glaoimid ar `process_lhs` agus `process_rhs` chun iad a thiontú ina luachanna a theastaíonn uainn le haghaidh SQL ag baint úsáide as an réad `compiler` a thuairiscítear roimhe seo. Tugann na modhanna seo tuples ina bhfuil roinnt SQL agus na paraiméadair atá le hidirphóladh isteach sa SQL sin, díreach mar is gá dúinn filleadh ónár modh as\_sql\`. Sa sampla thuas, filleann `process_lhs` ```('"údar”. ainm"', []) ``agus ``process_rhs``` filleann\`\` ('"%s"', \['Jack'\]) . Sa sampla seo ní raibh aon pharaiméadair ann don taobh clé, ach bheadh sé seo ag brath ar an réad atá againn, mar sin ní mór dúinn iad a áireamh sna paraiméadair a fhilleann muid fós.

Faoi dheireadh, déanaimid na codanna a chomhcheangal i abairt SQL le \<\>\`, agus soláthraímid na paraiméadair go léir don cheist. Ansin cuirimid tuple ar ais ina bhfuil an teaghrán SQL a ghintear agus na paraiméadair.

## Sampla claochladáin

Tá an cuardach saincheaptha thuas iontach, ach i gcásanna áirithe b'fhéidir gur mhaith leat a bheith in ann cuardaigh a shlánú le chéile. Mar shampla, is dóigh linn go bhfuilimid ag tógáil feidhmchlár áit ar mhaith linn úsáid a bhaint as an oibreoir ```abs () ``. Tá samhail ``Turgnamh``` againn a thaifeadann luach tosaigh, luach deiridh, agus an t-athrú (tús - deireadh). Ba mhaith linn gach turgnamh a fháil nuair a bhí an t-athrú cothrom le méid áirithe (Experiment.Objects.filter (change\_\_abs = 27) \`), nó nuair nár sháraigh sé méid áirithe (`Experiment.Objects.Filter (change__abs__lt=27)`).

> **Note**
>
> Tá an sampla seo dírithe beagán, ach léiríonn sé go deas an raon feidhmiúlachta atá indéanta ar bhealach neamhspleách cúltaca bunachar sonraí, agus gan feidhmiúlacht a dhúbailt cheana féin i Django.

Tosóimid trí chlaochladán `Absolutevalue` a scríobh. Úsáidfidh sé seo an fheidhm SQL ABS () chun an luach a athrú roimh chomparáid:

```
from django.db.models import Transform

class AbsoluteValue(Transform):
    lookup_name = "abs"
    function = "ABS"
```

Ansin, déanaimis é a chlárú le haghaidh `IntegerField`:

```
from django.db.models import IntegerField

IntegerField.register_lookup(AbsoluteValue)
```

Is féidir linn anois na ceisteanna a bhí againn roimhe seo a rith. Ghinfidh Experiment.Objects.Filter (change\_\_abs = 27) an SQL seo a leanas:

```sql
SELECT ... WHERE ABS("experiments"."change") = 27
```

Trí `Transform` a úsáid in ionad `Lookup` ciallaíonn sé go bhfuilimid in ann cuardaigh breise a shlánú ina dhiaidh sin. Mar sin, ginfidh Experiment.Objects.filter (change\_\_abs\_\_lt = 27) an SQL seo a leanas:

```sql
SELECT ... WHERE ABS("experiments"."change") < 27
```

Tabhair faoi deara, i gcás nach bhfuil aon chuardach eile sonraithe ann, léirmhíníonn Django `change__abs = 27` mar `change__abs__exact=27`.

Ligeann sé seo freisin an toradh a úsáid i gclásail `ORDER BY` agus DISTINCT ON\`. Mar shampla Experiment.Objects.Order\_by ('change\_\_abs') gineann:

```sql
SELECT ... ORDER BY ABS("experiments"."change") ASC
```

Agus ar bhunachair sonraí a thacaíonn le réimsí ar leith (mar shampla PostgreSQL), gineann Experiment.Objects.Distinct ('change\_\_abs') :

```sql
SELECT ... DISTINCT ON ABS("experiments"."change")
```

Agus tú ag lorg cé na cuardaigh atá incheadaithe tar éis an ```Transform` `a chur i bhfeidhm, úsáideann Django an tréith ``output_field`. Ní raibh gá dúinn é seo a shonrú anseo mar níor athraigh sé, ach ag glacadh go raibh “AbsoluteValue” á chur i bhfeidhm ar réimse éigin a léiríonn cineál níos casta (mar shampla pointe i gcoibhneas le bunús, nó uimhir chasta) ansin b'fhéidir gur theastaigh uainn a shonrú go dtugann an claochlú cineál `Floatfield` le haghaidh tuilleadh cuardaigh. Is féidir é seo a dhéanamh trí thréith ``output_field``` a chur leis an gclaochlú:

```
from django.db.models import FloatField, Transform

class AbsoluteValue(Transform):
    lookup_name = "abs"
    function = "ABS"

    @property
    def output_field(self):
        return FloatField()
```

Cinntíonn sé seo go n-iompraíonn cuardaigh breise mar `abs__lte` mar a dhéanfaidís do Floatfield .

## Cuardach éifeachtach `abs__lt` a scríobh

Agus an cuardach 'abs' scríofa thuas á úsáid agat, ní úsáidfidh an SQL a tháirgtear innéacsanna go héifeachtúil i gcásanna áirithe. Go háirithe, nuair a úsáidimid `change__abs__lt=27`, tá sé seo comhionann le `change__gt=-27` AGUS `change__lt=27`. (Maidir leis an gcás `lte` d'fhéadfaimis an SQL `BETWEEN` a úsáid).

Mar sin ba mhaith linn Experiment.Objects.filter (change\_\_abs\_\_lt = 27) an SQL seo a leanas a ghiniúint:

```sql
SELECT .. WHERE "experiments"."change" < 27 AND "experiments"."change" > -27
```

Is é seo a leanas an cur chun feidhme:

```
from django.db.models import Lookup

class AbsoluteValueLessThan(Lookup):
    lookup_name = "lt"

    def as_sql(self, compiler, connection):
        lhs, lhs_params = compiler.compile(self.lhs.lhs)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params + lhs_params + rhs_params
        return "%s < %s AND %s > -%s" % (lhs, rhs, lhs, rhs), params

AbsoluteValue.register_lookup(AbsoluteValueLessThan)
```

Tá cúpla rud suntasach ar siúl. Ar dtús, níl `Absolutevaluelessthan` ag glaoch ar ```process_lhs () ``. Ina áit sin scipeann sé claochlú na `lhs``` arna dhéanamh ag `AbsoluteValue` agus úsáideann sé an lhs\` bunaidh. Is é sin, ba mhaith linn “turgnaimh” a fháil.” athraigh “```ní ``ABS (“turgnaimh”.” athrú”) ``. Tá tagairt dhíreach do `self.lhs.lhs``` sábháilte mar ní féidir rochtain a fháil ar `AbsoluteValuelessthan` ach ón gcuardach `AbsoluteValue`, is é sin an lhs\` is sampla de AbsoluteValue\` i gcónaí.

Tabhair faoi deara freisin toisc go n-úsáidtear an dá thaobh arís agus arís agus arís eile sa cheist go gcaithfidh lhs\_params\` agus rhs\_params\` a bheith sna paramaí arís agus arís eile.

Déanann an cheist deiridh an t-inbhrú (`27` go -27\`) go díreach sa bhunachar sonraí. Is é an chúis atá leis seo a dhéanamh ná más rud éigin eile é an `self.rhs` seachas luach slámhshláir simplí (mar shampla tagairt F () ) ní féidir linn na claochlú a dhéanamh i Python.

> **Note**
>
> Déanta na fírinne, d'fhéadfaí an chuid is mó de na cuardaigh le \_\_abs a chur i bhfeidhm mar cheisteanna raon mar seo, agus ar fhormhór na gcúltaca bunachar sonraí is dóichí go mbeidh sé níos ciallmhaire é sin a dhéanamh mar is féidir leat úsáid a bhaint as na hinnéacsanna. Mar sin féin le PostgreSQL b'fhéidir gur mhaith leat innéacs a chur leis ar abs (athrú) a ligfeadh na ceisteanna seo a bheith an-éifeachtach.

## Sampla claochladáin déthaobh

Is é an sampla AbsoluteValue\` a phléamar roimhe seo ná claochlú a bhaineann leis an taobh clé den chuardach. D'fhéadfadh go mbeadh roinnt cásanna ann inar mian leat an claochlú a chur i bhfeidhm ar an taobh clé agus ar an taobh deise araon. Mar shampla, más mian leat tacar fiosrúcháin a scagadh bunaithe ar chomhionannas an taobh clé agus na láimhe deise go neamhíogair do roinnt feidhm SQL.

Déanaimis scrúdú ar chlaochlú cás-neamh-íogair Níl an claochlú seo an-úsáideach go praiticiúil toisc go dtagann dornán cuardaigh cás-neamh-íogair ionsuite le Django cheana féin, ach beidh sé ina léiriú deas ar chlaochlú déthaobhacha ar bhealach agnasach bunachar sonraí.

Sainmhínímid claochladán `Uppercase` a úsáideann an fheidhm SQL ```UPPER () ``chun na luachanna a athrú roimh chomparáid. Sainmhínímid: attr: `déthaobhach = Fíor <django.db.models.Transform.bilateral>`chun a léiriú gur chóir go mbeadh feidhm ag an gclaochlú seo le `lhs``` agus rhs\` araon:

```
from django.db.models import Transform

class UpperCase(Transform):
    lookup_name = "upper"
    function = "UPPER"
    bilateral = True
```

Ansin, déanaimis é a chlárú:

```
from django.db.models import CharField, TextField

CharField.register_lookup(UpperCase)
TextField.register_lookup(UpperCase)
```

Anois, ginfidh an tacar ceisteanna Author.Objects.Filter (name\_\_upper="doe”) ceist neamh-íogair cás mar seo:

```sql
SELECT ... WHERE UPPER("author"."name") = UPPER('doe')
```

## Forfheidhmithe malartacha a scríobh le haghaidh cuardaigh atá ann

Uaireanta éilíonn díoltóirí bunachar sonraí éagsúla SQL éagsúla don oibríocht chéanna. Mar shampla seo athscríobhfaimid cur i bhfeidhm saincheaptha do MySQL don oibreoir NotEqual. In ionad `<>` beimid ag úsáid `!=` oibreoir. (Tabhair faoi deara i ndáiríre go dtacaíonn beagnach gach bunachar sonraí leis an dá cheann, lena n-áirítear na bunachair shonraí oifigiúla go léir a fhaigheann tacaíocht ó Django).

Is féidir linn an t-iompar ar chúltaca ar leith a athrú trí fho-aicme de NoteQual\` a chruthú le modh as\_mysql\`:

```
class MySQLNotEqual(NotEqual):
    def as_mysql(self, compiler, connection, **extra_context):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return "%s != %s" % (lhs, rhs), params

Field.register_lookup(MySQLNotEqual)
```

Ansin is féidir linn é a chlárú le ```Field`. Tógann sé in áit an aicme bunaidh ``NoteQual``` mar tá an lookup\_name\` céanna aige.

Agus ceist á thiomsú, féachann Django ar dtús modhanna `as_%s% connection.vendor`, agus ansin titeann sé ar ais chuig `as_sql`. Is iad na hainmneacha díoltóra do na cúltaca ionsuite ná sqlite\`, postgresql\`, `oracle` agus `mysql`.

## Conas a chinneann Django na cuardaigh agus na hathshruithe a úsáidtear

I gcásanna áirithe b'fhéidir gur mhaith leat a athrú go dinimiciúil cén `Transform` nó `Lookup` ar ais bunaithe ar an ainm a chuirtear isteach, seachas é a shocrú. Mar shampla, d'fhéadfá réimse a bheith agat a stóráilíonn comhordanáidí nó gné treallach, agus ba mhaith leat comhréir mar .filter (coords\_\_x7=4) \`a cheadú chun na rudaí a thabhairt ar ais ina bhfuil luach 4 ag an 7ú comhordú. D'fhonn é seo a dhéanamh, dhéanfá \`\`get\_lookup\` a shárú le rud éigin mar:

```
class CoordinatesField(Field):
    def get_lookup(self, lookup_name):
        if lookup_name.startswith("x"):
            try:
                dimension = int(lookup_name.removeprefix("x"))
            except ValueError:
                pass
            else:
                return get_coordinate_lookup(dimension)
        return super().get_lookup(lookup_name)
```

Ansin shainmhíníodh `get_coordinate_lookup` go cuí chun fo-aicme `Lookup` a thabhairt ar ais a dhéileálann luach ábhartha `tois`.

Tá modh ainmnithe mar an gcéanna ar a dtugtar ```get_transformer () ``. Ba chóir go gcuirfeadh ``get_lookup () ``fo-aicme ``Lookup``` a thabhairt ar ais i gcónaí, agus `get_transformer ()` fo-aicme `Transform`. Tá sé tábhachtach a mheabhrú gur féidir rudaí Transform' a scagadh tuilleadh orthu, agus ní féidir rudaí \`\`Lookup\`.

Agus tú ag scagadh, mura bhfuil ach ainm cuardaigh amháin fágtha le réiteach, cuirfimid ag lorg `Lookup`. Má tá ainmneacha iolracha ann, cuardóidh sé ```Transform` `. Sa chás nach bhfuil ach ainm amháin ann agus nach bhfaightear ``Lookup```, cuirimid ag lorg `Transform` agus ansin an cuardach `` `cruth `` ar an Transform\` sin. Críochnaíonn gach seicheamh glaonna le `Lookup` i gcónaí. Chun soiléiriú:

- Glaofar ````.filter (myfield__mylookup) ```myfield.get_lookup ('mylookup')````.
- Tabharfaidh .filter (myfield\_\_mytransform\_\_mylookup) \`\`glaoch ar \`\`myfield.get\_transformer ('mytransformer')\`, agus ansin mytransform.get\_lookup ('mylookup') .
- Glaofar ```.filter (myfield__mytransformer) ``ar dtús ``myfield.get_lookup ('mytransformer')```, a theipeann air, mar sin tithfidh sé ar ais ar ```myfield.get_transformer ('mytransformer') ``agus ansin ``mytransform.get_lookup ('éacht')```.
