Ga naar inhoud

Deelnemingen en subqueries

Om de ene tafel naar de andere te voegen om ook gerelateerde modellen te laden, kunt u de volgende methode gebruiken.

  • select_related(related: Union[List, str]) -> QuerySet

  • select_all(follow: bool = True) -> QuerySet

  • prefetch_related(related: Union[List, str]) -> QuerySet

  • model

    • Model.load () methode
    • Query instellen Agent

    • QuerysetProxy.select_related(related: Union[List, str]) werkwijze

    • QuerysetProxy.select_all(follow: bool=True) werkwijze
    • QuerysetProxy.prefetch_related(related: Union[List, str]) werkwijze

Selecteer relevant

select_related(related: Union[List, str]) -> QuerySet

Hiermee kunnen gerelateerde modellen vooraf worden opgehaald tijdens dezelfde query.

Bij het gebruik van select\ _ lated wordt altijd slechts één query uitgevoerd tegen de database, wat betekent dat een (soms complexe) join wordt gegenereerd en later geneste modellen worden verwerkt in Python.

Gebruik de naam van de buitenlandse sleutel om het relevante model te verkrijgen.

Gebruik dubbele onderstrepingstekens tussen namen om gerelateerde modelrelaties te koppelen.

!!!Opmerking Als u uit Django komt, houd er dan rekening mee dat ormarselect\ _ lated in Django anders is dan - >, u kunt slechts één relatietype selecteren, terwijl u in ormar gerelateerd kunt selecteren, tegenover buitenlandse sleutel in buitenlandse sleutelrelaties (dus virtuele automatisch gegenereerde sleutels) En het veld ManyToMany (dus alle relaties in de huidige versie).

!!!Tip Om te bepalen welke modelvelden zijn geselecteerd, gebruikt u de velden () en behalve\ _ velden () QuerySet methoden.

!!!Tip Gebruik de methode order\ _ by () om de volgorde van modellen (master of geneste) te bepalen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Klasse Album (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    is _ best _ seller: bool = ormar. Booleaans (standaard = onwaar)

Klasse Track (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Album: Optioneel [Album] = ormar. ForeignKey (Album)
    Titel: str = ormar. String (max _ length = 100)
    Positie: int = ormar. Geheel ()
    play _ count: int = ormar. Geheel (nullable = Waar)


# Django-stijl
Album = afwachten Album.objects.select _ gerelateerd ("tracks") .all ()

# Python-stijl
Album = afwachten Album.objects.select _ gerelateerd (Album.tracks) .all ()

# zal album met alle kolommen tracks

U kunt een string of een lijst met strings (of een lijst met velden / velden) opgeven.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Klasse SchoolKlasse (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "schoolklassen")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    Afdeling: Facultatief [Afdeling] = ormar. ForeignKey (Afdeling, nullable = False)


Klasse Categorie (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "categorieën")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)


Klassestudent (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    SchoolKlasse: Optioneel [SchoolKlasse] = ormar. ForeignKey (SchoolKlasse)
    Categorie: Optioneel [Categorie] = ormar. ForeignKey (Categorie, nullable = Waar)


Klassenleraar (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    SchoolKlasse: Optioneel [SchoolKlasse] = ormar. ForeignKey (SchoolKlasse)
    Categorie: Optioneel [Categorie] = ormar. ForeignKey (Categorie, nullable = Waar)


# Django-stijl
Klassen = wachten op SchoolClass.objects.select _ gerelateerd (
    ["docenten _ _ categorie", "studenten"]) .all ()

# Python-stijl
Klassen = wachten op SchoolClass.objects.select _ gerelateerd (
    [SchoolKlasse. Docenten. categorie, SchoolKlasse. Studenten]) .alle ()

# zal lessen teruggeven met categorieën leraren en leraren
# evenals klasstudenten

Het veld Many2Many gedraagt zich precies hetzelfde, waar u de naam van het veld Many2Many kunt invoeren en het uiteindelijke model voor u kunt ophalen.

!!!WAARSCHUWING Als u het ForeignKey-veld tijdens alle zoekopdrachten instelt op niet-nullable (en daarom vereist), worden niet-nullable-modellen automatisch vooraf opgehaald, zelfs als u ze niet opneemt in de select\ _ lated.

!!!Merk op dat alle methoden die geen rijen retourneren expliciet een QuerySet-instantie retourneren, zodat u ze aan elkaar kunt koppelen

1
2
3
Dus operaties zoals `filter()`,`select_related()`,`limit()` en `offset()` etc. kunnen worden geketend.

Iets als `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

Alles selecteren

select_all(follow: bool = False) -> QuerySet

Standaard worden er geen relaties geladen wanneer u all () selecteert, en nogmaals, wanneer u select\ _ lated () gebruikt, moet u expliciet alle relaties specificeren die moeten worden geladen. Dit kan omslachtig zijn als u ook geneste relaties wilt opnemen.

Daarom is select\ _ all () geïntroduceerd, dus alle relaties van het model worden standaard geladen (in tegenstelling tot de all () methode).

Standaard worden alleen modellen toegevoegd die direct gerelateerd zijn aan het bovenliggende model (van waaruit de query wordt uitgevoerd).

Als u follow = True instelt, worden ook gerelateerde modellen van gerelateerde modellen toegevoegd.

!!!Info om niet vast te komen te zitten in een oneindige lus, omdat het gerelateerde model ook een relatie onderhoudt met het bovenliggende model dat toegang heeft tot de modelset.

1
2
3
4
Op die manier worden reeds bezochte modellen die genest zijn geladen, maar de ladingen niet
Volg ze inside.So Model A - > Model B - > Model C - > Model A - > Model X
Zal tweede Model A laden, maar zal nooit volgen in Model X.
Dergelijke geneste relaties moeten handmatig worden geladen.

Voorbeelddata zijn als volgt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
basis _ ormar _ config = OrmarConfig (
    Database = databanken. Database (DATABASE _ URL, force _ rollback = Waar),
    Metadata = sqlalchemie. MetaData (),
)


Klasse adres (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "adressen")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Straat: str = ormar. String (max _ length = 100, nullable = False)
    Aantal: int = ormar. Geheel getal (nullable = False)
    post _ code: str = ormar. Tekenreeks (max _ length = 20, nullable = False)



Klasse Branch (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "branches")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100, nullable = False)
    Adres = ormar. ForeignKey (Adres)


Klasse Bedrijf (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "bedrijven")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100, nullable = False, naam = "bedrijfsnaam")
    Opgericht: int = ormar. Integraal (nullable = Waar)
    Takken = ormar. ManyToMany (filiaal)

Om alle bedrijven met alle vestigingen en adressen te kiezen, hoeft u alleen maar te informeren:

1
2
3
4
Bedrijven = wachten op Company.objects.select _ all (volgen = Waar) .all ()

# dat overeenkomt met:
Bedrijven = wachten op Company.objects.select _ gerelateerd ('branches _ _ adres') .all ()

Natuurlijk is het in dit geval heel eenvoudig om expliciete relatienamen uit te geven in select\ _ lated, maar de voordelen van select\ _ all () worden duidelijk wanneer je meerdere relaties hebt.

Als Bedrijf bijvoorbeeld 3 relaties heeft en alle 3 relaties hun eigen 3 relaties hebben, moet u 9 relatiereeksen uitgeven om\ _ lated te selecteren en selecteert u\ _ all () kan de relatienaam niet wijzigen.

!!!Merk op dat u select\ _ all () kunt koppelen aan andere QuerySet-methoden zoals filter, exclude\ _ fields, etc. Om een relatie uit te sluiten, gebruikt u de aanroep met uitzondering van\ _ velden () met de (ook geneste) naam van de relatie om uit te sluiten.

prefetch correlatie

prefetch_related(related: Union[List, str]) -> QuerySet

Het is toegestaan om gerelateerde modellen vooraf op te halen tijdens query 's, maar in plaats van\ _ lated te selecteren, wordt elk volgend model opgehaald in een afzonderlijke databasequery.

Met prefetch\ _ lated voert elk model één query uit tegen de database, wat betekent dat u meerdere query 's achter elkaar zult uitvoeren.

Gebruik de naam van de buitenlandse sleutel om het relevante model te verkrijgen.

Gebruik dubbele onderstrepingstekens tussen namen om gerelateerde modelrelaties te koppelen.

!!!Tip Om te bepalen welke modelvelden zijn geselecteerd, gebruikt u de velden () en behalve\ _ velden () QuerySet methoden.

!!!Tip Gebruik de methode order\ _ by () om de volgorde van modellen (master of geneste) te bepalen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Klasse Album (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    is _ best _ seller: bool = ormar. Booleaans (standaard = onwaar)

Klasse Track (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Album: Optioneel [Album] = ormar. ForeignKey (Album)
    Titel: str = ormar. String (max _ length = 100)
    Positie: int = ormar. Geheel ()
    play _ count: int = ormar. Geheel (nullable = Waar)


# Django-stijl
Album = afwachten Album.objects.prefetch _ gerelateerd ("tracks") .all ()

# Python-stijl
Album = afwachten Album.objects.prefetch _ gerelateerd (Album.tracks) .all ()


# zal terugkeren album zal alle kolommen tracks

U kunt een string of een lijst met strings

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Klasse SchoolKlasse (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "schoolklassen")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    Afdeling: Facultatief [Afdeling] = ormar. ForeignKey (Afdeling, nullable = False)


Klasse Categorie (ormar. Model):
    ormar _ config = basis _ ormar _ config (tabelnaam = "categorieën")

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)


Klassestudent (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    SchoolKlasse: Optioneel [SchoolKlasse] = ormar. ForeignKey (SchoolKlasse)
    Categorie: Optioneel [Categorie] = ormar. ForeignKey (Categorie, nullable = Waar)


Klassenleraar (ormar. Model):
    ormar _ config = basis _ ormar _ config kopie ()

    Id: int = ormar. Geheel getal (primaire _ sleutel = waar)
    Naam: str = ormar. String (max _ length = 100)
    SchoolKlasse: Optioneel [SchoolKlasse] = ormar. ForeignKey (SchoolKlasse)
    Categorie: Optioneel [Categorie] = ormar. ForeignKey (Categorie, nullable = Waar)


# Django-stijl
Klassen = wachten op SchoolClass.objects.prefetch _ gerelateerd (
    ["docenten _ _ categorie", "studenten"]) .all ()

# Python-stijl
Klassen = wachten op SchoolClass.objects.prefetch _ gerelateerd (
    [SchoolKlasse. Docenten. categorie, SchoolKlasse. Studenten]) .alle ()
# zal lessen teruggeven met categorieën leraren en leraren
# evenals klasstudenten

Het veld Many2Many gedraagt zich precies hetzelfde, waar u de naam van het veld Many2Many kunt invoeren en het uiteindelijke model voor u kunt ophalen.

!!!-waarschuwing: als u het ForeignKey-veld tijdens alle zoekopdrachten instelt op niet-nullable (en daarom vereist), worden niet-nullable-modellen automatisch vooraf opgehaald, zelfs als u ze niet opneemt in de select\ _ lated.

!!!Merk op dat alle methoden die geen rijen retourneren expliciet een QuerySet-instantie retourneren, zodat u ze aan elkaar kunt koppelen

1
2
3
Dus operaties zoals `filter()`,`select_related()`,`limit()` en `offset()` etc. kunnen worden geketend.

Iets als `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

Selecteer correlatie versus prefetch correlatie

Welke van - > select\ _ lated of prefetch\ _ lated moet je gebruiken?

Nou, het hangt echt af van je gegevens. Het beste antwoord is om het zelf uit te proberen en te zien welke sneller / beter presteert binnen je systeembeperkingen.

Wat te onthouden:

prestaties

Aantal query 's: select\ _ lated voert altijd één query uit tegen de database, terwijl prefetch\ _ lated meerdere query 's uitvoert. Query (I / O) bewerkingen zijn meestal, maar niet noodzakelijk, de langzaamste.

Aantal rijen: Stel dat er 10.000 objecten zijn in tabel A, elk object heeft 3 onderliggende objecten in tabel B en vervolgens heeft elk object in tabel B 2 onderliggende objecten in tabel C. Als volgt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
                     model C
                   /
           Model B - Uitvoering C
         / 
Model A - Model B - Uitvoering C
       \           \ 
        \ Model C
         \
           Model B - Uitvoering C
                   \ 
                     model C

Dit betekent dat select\ _ lated altijd 60.000 rijen retourneert (10 000*3*2), later gecomprimeerd tot 10 000 modellen.

Hoeveel regels retourneren prefetch\ _ lated?

Nou, het hangt ervan af, als elk van de modellen B en C uniek is, dan retourneert het 10.000 rijen in de eerste query en 30.000 rijen in de tweede query (3 subitems van A in tabel B) Elk van deze is uniek) en 60.000 rijen (elk kind in tabel B is uniek). De 2 kinderen van model B in tabel C zijn uniek in de derde vraag).

In dit geval lijkt select\ _ lated een betere keuze, het zal niet alleen een query uitvoeren in vergelijking met 3 prefetches\ _ lated, maar het zal 60 retourneren in vergelijking met 100 000 prefetches\ _ lated (10 + 30 + 60k) 000 lijnen.

Maar wat als elk model A exact dezelfde drie model Bs heeft en elk model C exact hetzelfde model C? Select\ _ lated geeft nog steeds 60.000 rijen terug, terwijl prefetch\ _ lated 10.000 rijen retourneert voor model A, 3 rijen voor model B en 2 rijen voor model C. Dus een totaal van 10.006 rijen. Nu, afhankelijk van de structuur van het model (dat wil zeggen, als het een lange Text () veld, enz.), prefetch\ _ lated kan sneller zijn, hoewel het moet uitvoeren drie afzonderlijke query 's in plaats van één.

Geheugen

Ormar behoudt geen regedit voor geladen modellen.

Dit betekent dat u in het hierboven geselecteerde\ _ lated voorbeeld altijd 10.000 modellen A, 30.000 modellen B heeft (zelfs als het aantal unieke rijen in de database 3 is - select\ _ lated processing genereert een nieuwe voor elk bovenliggend model Submodel). En 60 000 modellen C.

Als rijen 1, 10, 100, enz. hetzelfde model B delen en u een van hen bijwerkt, worden de resterende rijen met hetzelfde kind niet onmiddellijk bijgewerkt. Als u uw wijzigingen in de database opslaat, zijn de wijzigingen alleen beschikbaar na het opnieuw laden (elk onderliggende item afzonderlijk laden of de hele query opnieuw laden). Dit betekent dat select\ _ lated meer geheugen zal gebruiken omdat elk onderliggende object wordt geïnstantieerd als een nieuw object

  • Hij gebruikte duidelijk zijn eigen ruimte.

!!!Houd er rekening mee dat dit in toekomstige releases kan veranderen als we besluiten caching te introduceren.

Waarschuwing: standaard zijn alle kinderen (of gebeurtenissen waarbij hetzelfde model meer dan tweemaal wordt geladen) volledig afzonderlijke en afzonderlijke Python-objecten, ook al vertegenwoordigen ze dezelfde rij in de database.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Ze zullen evalueren naar True wanneer ze worden vergeleken, dus in het bovenstaande voorbeeld:

```python
# will return True if child1 of both rows is the same child db row 
row1.child1 == row100.child1

# same here:
model1 = await Model.get(pk=1)
model2 = await Model.get(pk=1) # same pk = same row in db
# will return `True`
model1 == model2
```

but

```python
# will return False (note that id is a python `builtin` function not ormar one).
id(row1.child1) == id(ro100.child1)

# from above - will also return False
id(model1) == id(model2)
```

In plaats daarvan wordt met prefetch\ _ lated elk uniek onderscheidend kindmodel slechts één keer geïnstantieerd en wordt hetzelfde kindmodel gedeeld met alle oudermodellen. Dit betekent dat in het prefetch\ _ lated voorbeeld hierboven, als er 3 verschillende modellen zijn in tabel B en 2 verschillende modellen in tabel C, slechts 5 subnested modellen worden gedeeld tussen alle Model A-instanties. Dit betekent ook dat als u een eigenschap bijwerkt, alle bovenliggende objecten die eigenschap bijwerken omdat ze hetzelfde onderliggende object delen.

model werkwijze

Elk modelexemplaar heeft een set methoden om zichzelf op te slaan, bij te werken of te laden.

lading

U kunt een ForeignKey-gerelateerd model laden door de load () -methode aan te roepen.

Load () kan worden gebruikt om het model uit de database te vernieuwen als het door een ander proces is gewijzigd.

!!!Tip Lees meer over de load () methode in de modelmethode

QuerysetProxy methode

Wanneer u rechtstreeks toegang krijgt tot de relevante ManyToMany-velden en ReverseForeignKey, wordt een lijst met gerelateerde modellen geretourneerd.

Maar het toont ook een subset van de QuerySet API, zodat u rechtstreeks vanuit het bovenliggende model kunt filteren, maken, gerelateerde modellen kunt selecteren, enz.

Selecteer relevant

Precies hetzelfde als de select\ _ lated-functie hierboven, maar u kunt het gerelateerde object van het andere uiteinde van de relatie halen.

Ga

Alles selecteren

Precies hetzelfde als de select\ _ all-functie hierboven, maar u kunt het gerelateerde object aan de andere kant van de relatie ophalen.

Ga

prefetch correlatie

Precies hetzelfde als de prefetch\ _ lated-functie hierboven, maar u kunt gerelateerde objecten ophalen aan de andere kant van de relatie.

Ga