외국 키
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) 대상 모델 클래스를 채택하는 데 필요한 매개 변수가 있습니다.
Sqlalchemy 열 및 유형은 대상 모델에서 자동으로 가져옵니다.
- Sqlalchemy 열: 대상 모델 기본 키 열에 대한 클래스
- 유형(피단틱의 경우): 대상 모델의 유형
모델 정의
관계를 정의하려면 관련 모델을 가리키는 외래 키 필드를 추가합니다.
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)
|
역관계
외부 키 필드는 관계의 뒷면을 자동으로 등록합니다.
기본적으로 다음 코드 조각과 같이 하위(소스) 모델 이름 + 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())
|
역방향 관계는 API를 노출하여 부모의 관련 개체를 관리합니다.
역관계 건너뛰기
역방향 관계를 원하지 않는 경우 외부 키에 스킵_역방향=트루 플래그를 사용할 수 있습니다.
내부적으로 스킵_역방향 플래그를 설정한 경우 필드는 관계의 다른 쪽 끝에 여전히 등록되어 있으므로 다음을 수행할 수 있습니다.
- 역방향 모델의 관련 모델 필드별 필터링
- 리버스 모델에서 관련 모델 필드별로 _by 주문
그러나 당신은 할 수 없습니다:
- 관련 _name을 사용하여 역방향 모델에서 관련 필드에 액세스
- 모델의 반대쪽에서 상관 관계를 선택하더라도 반환된 모델은 역방향 인스턴스에 채워지지 않습니다(연결이 차단되지 않으므로 관계를 필터링하고 정렬할 수 있습니다).
- 관계는 모델 _dump() 및 모델 _dump_json()에 채워지지 않습니다.
- 가 사전 또는 json(파사피를 통해서도 )에서 채워지면 중첩된 관련 개체를 전달할 수 없습니다. 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
31
32
33
34
35
36 | 클래스 작성자(ormar. 모델):
ormar_config = base_ormar_config 사본()
ID: int = ormar. 정수(prial_key = 참)
첫 번째 이름: str = ormar. 문자열(max_long = 80)
성: str = ormar. 문자열(max_long = 80)
클래스 포스트(ormar. 모델):
ormar_config = base_ormar_config 사본()
ID: int = ormar. 정수(prial_key = 참)
제목: str = ormar. 문자열(max_long = 200)
작성자: 선택 사항 [작성자] = ormar. ForeignKey (작성자, _ = 참)
# 샘플 데이터 생성
작성자 = 작성자(first_name = "테스트", last_name = "작성자")
게시물 = 게시물(제목 = "테스트 게시물", 작성자 = 작성자)
주장post.author== 저자
저자를 주장하십시오. 게시물 #속성 오류!
#하지만 여전히 순서대로 사용할 수 있습니다_by
작성자 = (
기다리다 권한.ts._("").order_by("s__title").all()
)
저자를 주장하십시오 [0]. first_name== "테스트"
# 게시물은 명시적으로라도 작성자를 위해 채워지지 않습니다.
# _에 포함 - model_dump()에 게시물이 없습니다.
model_dump(제외={"id"})=={"first_name": "Test", "last_name": "Author"}
# 여전히 관련 모델의 필드를 필터링할 수 있습니다.
작성자 = 기다립니다. 인증. 개체. 필터 (ts__title="테스트 게시물") .all ()
저자를 주장하십시오 [0]. first_name== "테스트"
주장 렌 (저자) ==1
|
추가
상위에서 하위 모델을 추가하면 관련 모델이 현재 로드된 상위에 추가되고 하위 모델 외래 키 값을 설정하고 모델을 업데이트합니다.
| 부서 = 부서를 기다립니다(이름 = "과학").저장()
과정 = 과정(이름 = "수학", 완료 = 거짓) # 참고 - 저장되지 않음
department.courses 기다려 (코스)
course.pk 없음이 아니라고 주장 # 어린이 모델이 저장되었습니다
# 아동 모델에 대한 관계가 설정되고 FK 열이 db에 저장됩니다.
과정을 주장하십시오. 부서 == 부서
# 부모 모델의 관계도 설정됩니다.
주장department.courses[0] == 과정
|
!!!경고: 하위 모델을 관련 모델에 추가하려면 상위 모델의 기본 키 값이 데이터베이스에 있어야 합니다.
| 그렇지 않으면 ormar가 어린이의 ForeignKey 열 값을 설정할 수 없으므로 `RelationshipInstanceError` 를 올립니다.
상위 모델에 기본 키 값이 없는 경우.
즉,`department.courses.add()` 에 전화하기 전에 위의 부서를 저장해야 합니다.
|
!!!경고: 이 방법은 다대다 관계에서는 작동하지 않습니다. 이 경우 관계에 추가되기 전에 관계의 양쪽을 모두 저장해야 합니다.
제거
관련 모델이 하나씩 삭제됩니다.
역방향 관계에서 제거()를 호출하면 하위 모델이 제거되지 않고 ForeignKey 값이 null로 설정됩니다.
| # 위에서 계속
department.courses제거 대기(코스)
주장하다 (department.courses) == 0
# 과정은 여전히 존재하며 제거에 저장되었습니다.
course.pk 없음이 아니라고 주장
코스를 주장하십시오. 부서는 없음
# db에서 어린이를 제거하려면
기다리는 과정.삭제 ()
|
그러나 관계를 지우고 동시에 어린이를 삭제하려면 다음을 발행할 수 있습니다.
| # 이것은 관계를 명확하게 할 뿐만 아니라
# 그러나 db에서 관련 과정을 삭제합니다.
제거department.courses 기다립니다(과정, _ = 거짓)
|
분명한
한 번의 통화로 모든 관련 모델이 삭제됩니다.
삭제와 마찬가지로 기본적으로 지우기()는 하위 모델의 외래 키 열을 비웁니다(로드 여부에 관계없이 모두).
| # 이 학과와 관련된 모든 과정에 대한 무효 학과 열
기다려department.courses클리어()
|
데이터베이스에서 하위 항목을 완전히 제거하려면 Keep _ = False를 설정하십시오.
| # 이 부서와 관련된 모든 과정을 db에서 삭제합니다.
department.courses 클리어 기다리기(_ = 거짓)
|
쿼리 세트 에이전트
역관계는 일반 쿼리와 마찬가지로 관련 모델을 쿼리할 수 있는 QuerysetProxy API를 표시합니다.
사용 가능한 쿼리 세트 방법을 알아보려면 아래의 쿼리 프록시를 참조하십시오.
관련 이름
다음과 같이 관련 _name 매개 변수를 제공하여 관련 모델 필드 이름을 재정의할 수 있습니다.
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'))
|
!!!팁 액세스의 역관계는 순환 참조를 피하기 위해 wekref. 목록을 반환합니다.
!!!는 동일한 모델에 여러 관계를 제공할 때 경고합니다. 그렇지 않으면 관련 _name이 더 이상 자동으로 생성될 수 없습니다.
따라서 이 경우 하나를 제외한 모든 필드 또는 모든 관련 필드에 대해 관련 _ 이름을 제공해야 합니다(하나는 기본값 및 생성될 수 있음).
참조 작업
ForeignKey에서 참조하는 개체가 변경(삭제 또는 업데이트)되면 ormar는 ondelet 및 on 매개 변수로 지정된 SQL 제약 조건을 설정합니다.
온 삭제 및 온 업데이트에 대한 가능한 값은 ormar에서 찾을 수 있습니다. 참고 조치:
!!!참고 문자열 값을 ormar 대신 이 두 매개 변수에 직접 전달할 수 있습니다. 참조 액션이지만 무결성을 깨뜨릴 수 있으므로 권장하지 않습니다.
캐스케이드
상위(참조) 테이블의 행이 삭제(또는 업데이트)될 때마다 외부 키 열이 일치하는 하위(참조) 테이블의 해당 행도 삭제(또는 업데이트)됩니다. 이를 계단식 삭제(또는 업데이트)라고 합니다.
제한
참조된 테이블 또는 하위 테이블에 참조된 테이블의 값을 참조하는 행이 있으면 값을 업데이트하거나 삭제할 수 없습니다.
마찬가지로 참조된 테이블 또는 하위 테이블에 행에 대한 참조가 있는 한 행을 삭제할 수 없습니다.
설정_NULL
ForeignKey를 없음으로 설정합니다. 이것은 nullable이 True인 경우에만 가능합니다.
기본값 설정
ForeignKey를 기본값으로 설정합니다. ForeignKey의 서버_기본값을 설정해야 합니다.
!!!기본값은 허용되지 않습니다. 이 섹션에서 읽을 수 있는 서버 _ 기본값을 통해 이 작업을 수행해야 합니다.
아무것도 하지 마십시오.
아무 조치도 취하지 않고, 어떤 조치와 제한도 매우 유사하지 않습니다. NO ACTION과 RESTRICT의 주요 차이점은 NO ACTION의 경우 테이블을 변경하려는 시도 후에 참조 무결성 검사가 수행된다는 것입니다. 업데이트 또는 삭제 문을 실행하기 전에 RESTRICT가 확인합니다.
참조 무결성 검사가 실패하면 두 참조 작업이 모두 동일하게 작동합니다. 업데이트 또는 삭제 문으로 인해 오류가 발생합니다.
관계 설정
다양한 방법으로 관계를 맺을 수 있습니다.
모델 인스턴스
가장 분명한 것은 관련 모델 인스턴스를 생성자에게 전달하는 것입니다.
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)
|
사전
다음 옵션은 관련 모델의 키-값 사전을 사용하는 것입니다.
모델 _dump() 방법을 사용하여 사전을 직접 작성하거나 기존 모델에서 가져올 수 있습니다.
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)
|
!!!경고: 없음이 아닌 모든 경우 관련 모델의 기본 키 값이 데이터베이스에 있어야 합니다.
| 그렇지 않으면 데이터베이스 드라이버 라이브러리에서 무결성 오류가 발생합니다.
|