विषय पर बढ़ें

विदेशी कुंजी

ForeignKey(to: Model, *, name: str = None, unique: bool = False, nullable: bool = True, related_name: str = None, virtual: bool = False, onupdate: Union[ReferentialAction, str] = None, ondelete: Union[ReferentialAction, str] = None, **kwargs: Any) क्या लक्ष्य नमूना वर्ग को अपनाने के लिए आवश्यक पैरामीटर हैं।

Sqlalchकॉलम और प्रकार स्वचालित रूप से लक्ष्य नमूना से प्राप्त किए जाते हैं।

  • Sqlalchकॉलम: लक्ष्य नमूना प्राथमिक कुंजी कॉलम के लिए कक्षा
  • प्रकार (for pydantic): लक्ष्य का प्रकार नमूना

नमूना परिभाषित करें

एक रिश्ते को परिभाषित करने के लिए, एक विदेशी कुंजी क्षेत्र जोड़ें जो संबंधित नमूना को इंगित करता है।

 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
from typing import Optional

import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()


class Department(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Department] = ormar.ForeignKey(Department)

उलटा संबंध

विदेशी कुंजी क्षेत्र स्वचालित रूप से रिश्ते के रिवर्स साइड को पंजीकृत करता है।

डिफ़ॉल्ट रूप से, यह बच्चा है (source) नमूना नाम + s, जैसा कि निम्नलिखित कोड स्निपेट में है:

 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
44
45
import asyncio
from typing import Optional

import databases
import ormar
import sqlalchemy
from examples import create_drop_database

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL), metadata=sqlalchemy.MetaData()
)


class Department(ormar.Model):
    ormar_config = ormar_base_config.copy(tablename="departments")

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar_base_config.copy()

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Department] = ormar.ForeignKey(Department)


@create_drop_database(base_config=ormar_base_config)
async def verify():
    department = await Department(name="Science").save()
    course = Course(name="Math", completed=False, department=department)
    print(department.courses[0])
    # Will produce:
    # Course(id=None,
    #        name='Math',
    #        completed=False,
    #        department=Department(id=None, name='Science'))
    await course.save()


asyncio.run(verify())

माता-पिता से संबंधित वस्तुओं का प्रबंधन करने के लिए रिवर्स रिलेशनशिप एपीआई को उजागर करते हैं।

उलटा संबंध छोड़ें

यदि आप सुनिश्चित हैं कि आप रिवर्स रिलेशनशिप नहीं चाहते हैं, तो आप विदेशी कुंजी के लिए स्किप \ _ रिवर्स = ट्रू फ्लैग का उपयोग कर सकते हैं।

यदि आप स्किप \ _ रिवर्स फ्लैग को आंतरिक रूप से सेट करते हैं, तो फ़ील्ड अभी भी रिश्ते के दूसरे छोर पर पंजीकृत है, इसलिए आप कर सकते हैं:

  • रिवर्स में प्रासंगिक नमूना फ़ील्ड द्वारा फ़िल्टर नमूना
  • रिवर्स मॉडल में संबंधित मॉडल फील्ड्स द्वारा ऑर्डर \ _

लेकिन आप नहीं कर सकते:

  • रिवर्स नमूना से संबंधित फ़ील्ड तक पहुँचने के लिए संबंधित \ _ नाम का उपयोग करें
  • यहां तक कि अगर आप नमूना के रिवर्स साइड से सहसंबंध का चयन करते हैं, तो लौटे नमूना रिवर्स उदाहरण में आबादी नहीं होगी (कोई कनेक्शन अवरुद्ध नहीं किया जाएगा, इसलिए आप अभी भी रिश्ते को फ़िल्टर और सॉर्ट कर सकते हैं)।
  • रिश्ता नमूना में आबाद नहीं है \ _ डंप () और नमूना \ _ डंप \ _ json ()
  • शब्दकोश या JSसे भरते समय (also via fastapi), आप नेस्टेड संबंधित ऑब्जेक्ट पास नहीं कर सकते। pydकॉन्फ़िगरेशन में अतिरिक्त सेटिंग्स के आधार पर, इसे अनदेखा कर दिया जाएगा या एक त्रुटि फेंक दी जाएगी।

उदाहरण:

 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
कक्षा लेखक (ormar. Model):
    ormar _ config = आधार _ ormar _ config कॉपी ()

    आईडी: int = ormar। पूर्णांक (primary_key = True)
    पहला_नाम: str = ormar। स्ट्रिंग (max_length = 80)
    last_name: str = ormar। स्ट्रिंग (max_length = 80)


क्लास पोस्ट (ormar. Model):
    ormar _ config = आधार _ ormar _ config कॉपी ()

    आईडी: int = ormar। पूर्णांक (primary_key = True)
    शीर्षक: str = ormar। स्ट्रिंग (max_length = 200)
    लेखक: वैकल्पिक [लेखक: = ormar। विदेशी (लेखक, स्किप _ रिवर्स = सच)

# नमूना डेटा बनाएं
लेखक = लेखक (first_name = "Test", last_name = "Author")
पोस्ट = पोस्ट (शीर्षक = "टेस्ट पोस्ट", लेखक = लेखक)

post.author = = लेखक # ठीक है
Author.posts # विशेषता त्रुटि!

# लेकिन अभी भी ऑर्डर_बाय में उपयोग कर सकते हैं
लेखक = (
    Author.objects.select_related ("posts") .order_by ("posts__title").सभी ()
)
लेखकों का दावा करें [0]। पहला _ नाम = = "टेस्ट"

# ध्यान दें कि पदों को स्पष्ट रूप से भले ही लेखकों के लिए आबादी नहीं है
# select_related में शामिल - मॉडल _ डंप () में कोई पोस्ट नोट न करें
मॉडल _ डंप (exclude ={"id"}) =={"first_name": "Test", "last_name": "Author"}

#still संबंधित मॉडल के क्षेत्रों के माध्यम से फ़िल्टर कर सकता है
लेखक = लेखक का इंतजार करें। फ़िल्टर (posts__title="Test post").all ()
लेखकों का दावा करें [0]। पहला _ नाम = = "टेस्ट"
अभिकथन लेन (लेखक) == 1

जोड़ें

माता-पिता से बच्चे नमूना जोड़ने से संबंधित नमूना वर्तमान में लोड किए गए माता-पिता में जोड़ा जा सकता है, बच्चे नमूना विदेशी कुंजी मान सेट किया जा सकता है, और नमूना अपडेट किया जा सकता है।

1
2
3
4
5
6
7
8
9
विभाग = प्रतीक्षा विभाग (name = "Science").सहेजें ()
पाठ्यक्रम = पाठ्यक्रम (नाम = "गणित", पूरा = गलत) # नोट - सहेजा नहीं गया

department.courses (कोर्स)
जोर course.pk कोई नहीं है # बच्चा नमूना बचाया गया था
# बाल नमूना पर संबंध सेट है और एफके कॉलम डीबी में सहेजा गया है
पाठ्यक्रम का दावा करें। विभाग = = विभाग
# माता-पिता नमूना पर संबंध भी निर्धारित है
department.courses करें

!!!चेतावनी: यदि आप किसी बच्चे नमूना संबंधित नमूना में जोड़ना चाहते हैं, तो मूल नमूना का प्राथमिक कुंजी मान डेटाबेस में मौजूद होना चाहिए।

1
2
3
4
अन्यथा ओमार उठाएगा `RelationshipInstanceError` चूंकि यह बच्चे के के स्तंभ मान को सेट नहीं कर सकता है 
यदि माता-पिता नमूना कोई प्राथमिक कुंजी मूल्य नहीं है।

यह माध्य कि आपके द्वारा कॉल करने से पहले विभाग के ऊपर उदाहरण को सहेजना होगा `department.courses.add()` हाँ।

!!!चेतावनी: यह विधि कई-से-कई रिश्तों के साथ काम नहीं करती है - इस मामले में, रिश्ते में जोड़े जाने से पहले रिश्ते के दोनों पक्षों को बचाया जाना चाहिए।

खत्म करना

संबंधित मॉडल एक-एक करके हटा दिए जाते हैं।

रिवर्स रिलेशनशिप में, कॉलिंग रिमूव () सबमॉडल को नहीं हटाता है, लेकिन इसके फॉरेनकी मान को शून्य करने के लिए सेट करता है।

1
2
3
4
5
6
7
8
9
# ऊपर से जारी
हटाने department.courses प्रतीक्षा करें (कोर्स)
लेन डालें (department.courses) == 0
#course अभी भी मौजूद है और हटाने में सहेजा गया था
course.pk कोई नहीं है
पाठ्यक्रम का दावा करें। विभाग कोई नहीं है

# बच्चों को db से हटाने के लिए
प्रतीक्षारत पाठ्यक्रम। ()

लेकिन अगर आप रिश्ते को साफ करना चाहते हैं और एक ही समय में बच्चों को हटाना चाहते हैं, तो आप जारी कर सकते हैं:

1
2
3
# यह न केवल संबंध को स्पष्ट करेगा
# लेकिन db से संबंधित पाठ्यक्रमों को भी हटा दें
हटाने department.courses प्रतीक्षा करें (बेशक, _ उलट = गलत)

स्पष्ट

एक एकल कॉल सभी संबंधित मॉडल को हटा देता है।

विलोपन के साथ, डिफ़ॉल्ट रूप से, स्पष्ट () चाइल्ड नमूना पर फॉरेकी कॉलम खाली कर देगा (सभी, चाहे वे लोड किए गए हों या नहीं)।

1
2
इस विभाग से संबंधित सभी पाठ्यक्रमों पर #nulls विभाग कॉलम
department.courses स्पष्ट ()

यदि आप डेटाबेस से एक चाइल्ड आइटम को पूरी तरह से हटाना चाहते हैं, तो \ _ उलट = गलत रखें सेट करें

1
2
# इस विभाग से संबंधित सभी पाठ्यक्रमों को db से हटा देता है
स्पष्ट department.courses प्रतीक्षा करें (keep_versed = False)

क्वेरी सेट एजेंट

उलटा संबंध QueryProएपीआई को उजागर करता है, जो आपको संबंधित मॉडल को क्वेरी करने की अनुमति देता है जैसे आप एक सामान्य क्वेरी करेंगे।

क्वेरीसेट के कौन से तरीके उपलब्ध हैं, यह जानने के लिए नीचे दिए गए क्वेरीसेटप्रॉक्सी पढ़ें

संबंधित नाम

आप संबंधित \ _ नाम पैरामीटर प्रदान करके संबंधित नमूना फ़ील्ड नामों को ओवरराइड कर सकते हैं:

 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
from typing import Optional

import databases
import ormar
import sqlalchemy

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL), metadata=sqlalchemy.MetaData()
)


class Department(ormar.Model):
    ormar_config = ormar_base_config.copy()

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar_base_config.copy()

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Department] = ormar.ForeignKey(
        Department, related_name="my_courses"
    )


department = Department(name="Science")
course = Course(name="Math", completed=False, department=department)

print(department.my_courses[0])
# Will produce:
# Course(id=None,
#        name='Math',
#        completed=False,
#        department=Department(id=None, name='Science'))

!!!टिप एक्सेस पर उलटा संबंध परिपत्र संदर्भों से बचने के लिए wek.सूची लौटाता है।

!!!चेतावनी जब आप एक ही नमूना के लिए कई संबंधों की आपूर्ति करते हैं, तो अन्यथा संबंधित \ _ नाम अब आपके लिए स्वचालित रूप से उत्पन्न नहीं हो सकता है। इसलिए, इस मामले में, आपको एक को छोड़कर सभी फ़ील्ड के लिए संबंधित \ _ नाम प्रदान करना होगा (एक डिफ़ॉल्ट और उत्पन्न हो सकता है) या सभी संबंधित फ़ील्ड के लिए।

संदर्भ कार्रवाई

जब द्वारा संदर्भित कोई ऑब्जेक्ट बदल जाता है (deletes or updates), ormar onऔर onमापदंडों द्वारा निर्दिष्ट SQL बाधाओं को सेट करता है।

onऔर onके लिए संभावित मान ormar में पाए जा सकते हैं। संदर्भ कार्रवाई:

!!!नोट आप ormar के बजाय इन दो मापदंडों पर सीधे स्ट्रिंग मान पास कर सकते हैं। ReferentialAction, लेकिन यह अनुशंसित नहीं है क्योंकि यह अखंडता का उल्लंघन करेगा।

कैस्केड

जब भी माता-पिता (संदर्भित) तालिका में एक पंक्ति हटा दी जाती है (or updated), विदेशी कुंजी स्तंभों के मिलान के साथ बच्चे (संदर्भित) तालिका में संबंधित पंक्ति भी हटा दी गई है (or updated). इसे कैस्केडिंग डिलीट कहा जाता है (or update).

प्रतिबंध

जब संदर्भित तालिका या सबटेबल में एक पंक्ति होती है जो संदर्भित तालिका में मान का संदर्भ देती है, तो मान को अपडेट या हटाया नहीं जा सकता है।

इसी तरह, जब तक कि संदर्भित तालिका या चाइल्ड टेबल में एक पंक्ति का संदर्भ है, तो पंक्ति को हटाया नहीं जा सकता है।

सेट \ _ NL

कोई नहीं करने के लिए विदेशी कुंजी सेट करें; यह केवल तभी संभव है जब अशक्त सत्य हो।

डिफ़ॉल्ट मान सेट करें

के डिफ़ॉल्ट मान पर सेट करें; के लिए सर्वर \ _ डिफ़ॉल्ट सेट किया जाना चाहिए।

!!!ध्यान दें कि डिफ़ॉल्ट की अनुमति नहीं है, आपको सर्वर \ _ डिफ़ॉल्ट के माध्यम से ऐसा करना होगा, जिसके बारे में आप इस अनुभाग में पढ़ सकते हैं।

कुछ मत करो।

कोई कार्रवाई नहीं की गई; कोई कार्रवाई और प्रतिबंध बहुत समान नहीं है। NO ACTION और RESTRके बीच मुख्य अंतर यह है कि, NO ACTION के लिए, तालिका को बदलने के प्रयास के बाद संदर्भित अखंडता जांच की जाती है। UATE या DELEस्टेटमेंट को निष्पादित करने के प्रयास से पहले RESTRजाँच करता है। यदि संदर्भित अखंडता जांच विफल हो जाती है, तो दोनों संदर्भित संचालन समान व्यवहार करते हैं: एक अद्यतन या DELEकथन के परिणामस्वरूप एक त्रुटि होती है।

संबंध सेटिंग्स

आप विभिन्न तरीकों से संबंध स्थापित कर सकते हैं।

मॉडल उदाहरण

सबसे स्पष्ट एक प्रासंगिक मॉडल उदाहरण को कंस्ट्रक्टर को पारित करना है।

 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
44
45
from typing import Dict, Optional, Union

import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()


class Department(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Union[Department, Dict]] = ormar.ForeignKey(Department)


department = Department(name="Science")

# set up a relation with actual Model instance
course = Course(name="Math", completed=False, department=department)

# set up  relation with only related model pk value
course2 = Course(name="Math II", completed=False, department=department.pk)

# set up a relation with dictionary corresponding to related model
course3 = Course(name="Math III", completed=False, department=department.model_dump())

# explicitly set up None
course4 = Course(name="Math III", completed=False, department=None)

प्राथमिक कुंजी मान

आप संबंधित नमूना के केवल PK कॉलम मानों का उपयोग करके संबंध भी सेट कर सकते हैं।

 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
44
45
from typing import Dict, Optional, Union

import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()


class Department(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Union[Department, Dict]] = ormar.ForeignKey(Department)


department = Department(name="Science")

# set up a relation with actual Model instance
course = Course(name="Math", completed=False, department=department)

# set up  relation with only related model pk value
course2 = Course(name="Math II", completed=False, department=department.pk)

# set up a relation with dictionary corresponding to related model
course3 = Course(name="Math III", completed=False, department=department.model_dump())

# explicitly set up None
course4 = Course(name="Math III", completed=False, department=None)

शब्दकोश

अगला विकल्प प्रासंगिक नमूना के कुंजी-मूल्य शब्दकोश का उपयोग करना है।

आप शब्दकोश का निर्माण स्वयं कर सकते हैं या इसे किसी मौजूदा नमूना से प्राप्त कर सकते हैं नमूना () विधि।

 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
44
45
from typing import Dict, Optional, Union

import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()


class Department(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Union[Department, Dict]] = ormar.ForeignKey(Department)


department = Department(name="Science")

# set up a relation with actual Model instance
course = Course(name="Math", completed=False, department=department)

# set up  relation with only related model pk value
course2 = Course(name="Math II", completed=False, department=department.pk)

# set up a relation with dictionary corresponding to related model
course3 = Course(name="Math III", completed=False, department=department.model_dump())

# explicitly set up None
course4 = Course(name="Math III", completed=False, department=None)

कुछ भी तो नहीं।

अंत में, आप स्पष्ट रूप से इसे कोई नहीं पर सेट कर सकते हैं (डिफ़ॉल्ट व्यवहार यदि कोई मूल्य पारित नहीं हुआ है)।

 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
44
45
from typing import Dict, Optional, Union

import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()


class Department(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class Course(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    completed: bool = ormar.Boolean(default=False)
    department: Optional[Union[Department, Dict]] = ormar.ForeignKey(Department)


department = Department(name="Science")

# set up a relation with actual Model instance
course = Course(name="Math", completed=False, department=department)

# set up  relation with only related model pk value
course2 = Course(name="Math II", completed=False, department=department.pk)

# set up a relation with dictionary corresponding to related model
course3 = Course(name="Math III", completed=False, department=department.model_dump())

# explicitly set up None
course4 = Course(name="Math III", completed=False, department=None)

!!!चेतावनी: सभी गैर-कोई नहीं मामलों में, संबंधित नमूना का प्राथमिक कुंजी मूल्य डेटाबेस में मौजूद होना चाहिए।

1
अन्यथा आपके डेटाबेस ड्राइवर लाइब्रेरी द्वारा एक इंटीग्रिटीएरर उठाया जाएगा।