Conas cuardaigh saincheaptha a scríobhLink to this heading
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 cuardaighLink to this heading
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:
"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áinLink to this heading
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)).
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:
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:
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:
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') ``:
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íobhLink to this heading
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:
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.
Sampla claochladáin déthaobhLink to this heading
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:
SELECT ... WHERE UPPER("author"."name") = UPPER('doe')
Forfheidhmithe malartacha a scríobh le haghaidh cuardaigh atá annLink to this heading
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áidtearLink to this heading
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 armyfield.get_transformer ('mytransformer') ``agus ansin ``mytransform.get_lookup ('éacht').