From: Zssaer <45691504+Zssaer@users.noreply.github.com> Date: Mon, 31 Oct 2022 17:56:49 +0000 (+0800) Subject: 🌐 Add Chinese translation for `docs/zh/docs/tutorial/sql-databases.md` (#4999) X-Git-Tag: 0.85.2~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9974c4b6ac4949198048fd8a432996d0c1760740;p=thirdparty%2Ffastapi%2Ffastapi.git 🌐 Add Chinese translation for `docs/zh/docs/tutorial/sql-databases.md` (#4999) Co-authored-by: mkdir700 <56359329+mkdir700@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000..6b354c2b6d --- /dev/null +++ b/docs/zh/docs/tutorial/sql-databases.md @@ -0,0 +1,770 @@ +# SQL (å ³ç³»å) æ°æ®åº + +**FastAPI**ä¸éè¦ä½ 使ç¨SQL(å ³ç³»å)æ°æ®åºã + +使¯æ¨å¯ä»¥ä½¿ç¨ä»»ä½æ¨æ³è¦çå ³ç³»åæ°æ®åºã + +å¨è¿éï¼è®©æä»¬çä¸ä¸ªä½¿ç¨ç[SQLAlchemy](https://www.sqlalchemy.org/)ç示ä¾ã + +æ¨å¯ä»¥å¾å®¹æå°å°SQLAlchemyæ¯æä»»ä½æ°æ®åºï¼åï¼ + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Serverï¼ççå ¶å®æ°æ®åº + +卿¤ç¤ºä¾ä¸ï¼æä»¬å°ä½¿ç¨**SQLite**ï¼å 为å®ä½¿ç¨å个æä»¶å¹¶ä¸ å¨Pythonä¸å ·æéææ¯æãå æ¤ï¼æ¨å¯ä»¥å¤å¶æ¤ç¤ºä¾å¹¶æåæ ·æ¥è¿è¡å®ã + +ç¨åï¼å¯¹äºæ¨ç产å级å«çåºç¨ç¨åºï¼æ¨å¯è½ä¼è¦ä½¿ç¨å**PostgreSQL**è¿æ ·çæ°æ®åºæå¡å¨ã + +!!! tip + è¿å¿æä¸ä¸ª**FastAPI**å**PostgreSQL**ç宿¹é¡¹ç®çæå¨ï¼å ¨é¨åºäº**Docker**ï¼å æ¬åç«¯åæ´å¤å·¥å ·ï¼https://github.com/tiangolo/full-stack-fastapi-postgresql + +!!! note + 请注æï¼å¤§é¨åä»£ç æ¯`SQLAlchemy`çæ å代ç ï¼æ¨å¯ä»¥ç¨äºä»»ä½æ¡æ¶ãFastAPIç¹å®ç代ç åå¾å¸¸ä¸æ ·å°ã + +## ORMsï¼å¯¹è±¡å ³ç³»æ å°ï¼ + +**FastAPI**å¯ä¸ä»»ä½æ°æ®åºå¨ä»»ä½æ ·å¼çåºä¸ä¸èµ·ä¸ æ°æ®åºè¿è¡éä¿¡ã + +ä¸ç§å¸¸è§çæ¨¡å¼æ¯ä½¿ç¨âORMâï¼å¯¹è±¡å ³ç³»æ å°ã + +ORM å ·æå¨ä»£ç åæ°æ®åºè¡¨ï¼â*å ³ç³»åâï¼ä¸ç**对象**ä¹é´è½¬æ¢ï¼â*æ å°*âï¼çå·¥å ·ã + +ä½¿ç¨ ORMï¼æ¨é常ä¼å¨ SQL æ°æ®åºä¸å建ä¸ä¸ªä»£è¡¨æ å°çç±»ï¼è¯¥ç±»çæ¯ä¸ªå±æ§ä»£è¡¨ä¸ä¸ªåï¼å ·æåç§°åç±»åã + +ä¾å¦ï¼ä¸ä¸ªç±»`Pet`å¯ä»¥è¡¨ç¤ºä¸ä¸ª SQL 表`pets`ã + +è¯¥ç±»çæ¯ä¸ª*å®ä¾å¯¹è±¡é½ä»£è¡¨æ°æ®åºä¸çä¸è¡æ°æ®ã* + +åä¾å¦ï¼ä¸ä¸ªå¯¹è±¡`orion_cat`ï¼`Pet`çä¸ä¸ªå®ä¾ï¼å¯ä»¥æä¸ä¸ªå±æ§`orion_cat.type`, å¯¹æ æ°æ®åºä¸ç`type`åãå¹¶ä¸è¯¥å±æ§çå¼å¯ä»¥æ¯å ¶å®ï¼ä¾å¦`"cat"`ã + +è¿äº ORM è¿å ·æå¨è¡¨æå®ä½ä¹é´å»ºç«å ³ç³»çå·¥å ·ï¼æ¯å¦å建å¤è¡¨å ³ç³»ï¼ã + +è¿æ ·ï¼æ¨è¿å¯ä»¥æ¥æä¸ä¸ªå±æ§`orion_cat.owner`ï¼å®å å«è¯¥å® ç©ææè çæ°æ®ï¼è¿äºæ°æ®åèªå¦å¤ä¸ä¸ªè¡¨ã + +å æ¤ï¼`orion_cat.owner.name`å¯è½æ¯è¯¥å® ç©ä¸»äººçå§åï¼æ¥èªè¡¨`owners`ä¸çå`name`ï¼ã + +å®å¯è½æä¸ä¸ªå`"Arquilian"`(ä¸ç§ä¸å¡é»è¾)ã + +彿¨å°è¯ä»æ¨çå® ç©å¯¹è±¡è®¿é®å®æ¶ï¼ORM å°å®æææå·¥ä½ä»¥ä»ç¸åºç表*ææè é£éåè·åä¿¡æ¯ã* + +常è§ç ORM ä¾å¦ï¼Django-ORMï¼Django æ¡æ¶çä¸é¨åï¼ãSQLAlchemy ORMï¼SQLAlchemy çä¸é¨åï¼ç¬ç«äºæ¡æ¶ï¼å Peeweeï¼ç¬ç«äºæ¡æ¶ï¼çã + +å¨è¿éï¼æä»¬å°çå°å¦ä½ä½¿ç¨**SQLAlchemy ORM**ã + +ä»¥ç±»ä¼¼çæ¹å¼ï¼æ¨ä¹å¯ä»¥ä½¿ç¨ä»»ä½å ¶ä» ORMã + +!!! tip + å¨ææ¡£ä¸ä¹æä¸ç¯ä½¿ç¨ Peewee ççæçæç« ã + +## æä»¶ç»æ + +对äºè¿äºç¤ºä¾ï¼åè®¾æ¨æä¸ä¸ªå为çç®å½`my_super_project`ï¼å ¶ä¸å å«ä¸ä¸ªå为çåç®å½`sql_app`ï¼å ¶ç»æå¦ä¸ï¼ + +``` +. +âââ sql_app + âââ __init__.py + âââ crud.py + âââ database.py + âââ main.py + âââ models.py + âââ schemas.py +``` + +该æä»¶`__init__.py`åªæ¯ä¸ä¸ªç©ºæä»¶ï¼ä½å®åè¯ Python å ¶ä¸`sql_app`çæææ¨¡åï¼Python æä»¶ï¼é½æ¯ä¸ä¸ªå ã + +ç°å¨è®©æä»¬ççæ¯ä¸ªæä»¶/模åçä½ç¨ã + +## å建 SQLAlchemy é¨ä»¶ + +让æä»¬æ¶åå°æä»¶`sql_app/database.py`ã + +### å¯¼å ¥ SQLAlchemy é¨ä»¶ + +```Python hl_lines="1-3" +{!../../../docs_src/sql_databases/sql_app/database.py!} +``` + +### 为 SQLAlchemy å®ä¹æ°æ®åº URLå°å + +```Python hl_lines="5-6" +{!../../../docs_src/sql_databases/sql_app/database.py!} +``` + +å¨è¿ä¸ªä¾åä¸ï¼æä»¬æ£å¨âè¿æ¥âå°ä¸ä¸ª SQLite æ°æ®åºï¼ç¨ SQLite æ°æ®åºæå¼ä¸ä¸ªæä»¶ï¼ã + +该æä»¶å°ä½äºæä»¶ä¸çåä¸ç®å½ä¸`sql_app.db`ã + +è¿å°±æ¯ä¸ºä»ä¹æåä¸é¨åæ¯`./sql_app.db`. + +妿æ¨ä½¿ç¨çæ¯**PostgreSQL**æ°æ®åºï¼ååªéåæ¶æ³¨é该è¡ï¼ + +```Python +SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db" +``` + +...å¹¶æ ¹æ®æ¨çæ°æ®åºæ°æ®åç¸å ³åæ®ï¼ä¹éç¨äº MySQLãMariaDB æä»»ä½å ¶ä»ï¼å¯¹å ¶è¿è¡è°æ´ã + +!!! tip + + å¦ææ¨æ³ä½¿ç¨ä¸åçæ°æ®åºï¼è¿æ¯å°±æ¯æ¨å¿ 须修æ¹çå°æ¹ã + +### å建 SQLAlchemy 弿 + +ç¬¬ä¸æ¥ï¼å建ä¸ä¸ª SQLAlchemyçâ弿âã + +æä»¬ç¨åä¼å°è¿ä¸ª`engine`å¨å ¶ä»å°æ¹ä½¿ç¨ã + +```Python hl_lines="8-10" +{!../../../docs_src/sql_databases/sql_app/database.py!} +``` + +#### 注æ + +åæ°: + +```Python +connect_args={"check_same_thread": False} +``` + +...ä» ç¨äº`SQLite`ï¼å¨å ¶ä»æ°æ®åºä¸éè¦å®ã + +!!! info "ææ¯ç»è" + + é»è®¤æ åµä¸ï¼SQLite åªå 许ä¸ä¸ªçº¿ç¨ä¸å ¶éä¿¡ï¼å设æå¤ä¸ªçº¿ç¨çè¯ï¼ä¹åªå°å¤çä¸ä¸ªç¬ç«ç请æ±ã + + è¿æ¯ä¸ºäºé²æ¢æå¤å°ä¸ºä¸åçäºç©ï¼ä¸åç请æ±ï¼å ±äº«ç¸åçè¿æ¥ã + + 使¯å¨ FastAPI ä¸ï¼æ®é使ç¨def彿°ï¼å¤ä¸ªçº¿ç¨å¯ä»¥ä¸ºåä¸ä¸ªè¯·æ±ä¸æ°æ®åºäº¤äºï¼æä»¥æä»¬éè¦ä½¿ç¨`connect_args={"check_same_thread": False}`æ¥è®©SQLiteå è®¸è¿æ ·ã + + æ¤å¤ï¼æä»¬å°ç¡®ä¿æ¯ä¸ªè¯·æ±é½å¨ä¾èµé¡¹ä¸è·å¾èªå·±çæ°æ®åºè¿æ¥ä¼è¯ï¼å æ¤ä¸éè¦è¯¥é»è®¤æºå¶ã + +### å建ä¸ä¸ª`SessionLocal`ç±» + +æ¯ä¸ªå®ä¾`SessionLocal`é½ä¼æ¯ä¸ä¸ªæ°æ®åºä¼è¯ãå½ç¶è¯¥ç±»æ¬èº«è¿ä¸æ¯æ°æ®åºä¼è¯ã + +使¯ä¸æ¦æä»¬å建äºä¸ä¸ª`SessionLocal`ç±»çå®ä¾ï¼è¿ä¸ªå®ä¾å°æ¯å®é çæ°æ®åºä¼è¯ã + +æä»¬å½å宿¯`SessionLocal`为äºå°å®ä¸æä»¬ä» SQLAlchemy å¯¼å ¥ç`Session`åºå«å¼æ¥ã + +ç¨åæä»¬å°ä½¿ç¨`Session`ï¼ä» SQLAlchemy å¯¼å ¥çé£ä¸ªï¼ã + +è¦å建`SessionLocal`ç±»ï¼è¯·ä½¿ç¨å½æ°`sessionmaker`ï¼ + +```Python hl_lines="11" +{!../../../docs_src/sql_databases/sql_app/database.py!} +``` + +### å建ä¸ä¸ª`Base`ç±» + +ç°å¨æä»¬å°ä½¿ç¨`declarative_base()`è¿åä¸ä¸ªç±»ã + +ç¨åæä»¬å°ç¨è¿ä¸ªç±»ç»§æ¿ï¼æ¥å建æ¯ä¸ªæ°æ®åºæ¨¡åæç±»ï¼ORM 模åï¼ï¼ + +```Python hl_lines="13" +{!../../../docs_src/sql_databases/sql_app/database.py!} +``` + +## åå»ºæ°æ®åºæ¨¡å + +ç°å¨è®©æä»¬ççæä»¶`sql_app/models.py`ã + +### ç¨`Base`ç±»æ¥å建 SQLAlchemy 模å + +æä»¬å°ä½¿ç¨æä»¬ä¹åå建ç`Base`ç±»æ¥å建 SQLAlchemy 模åã + +!!! tip + SQLAlchemy 使ç¨çâ**模å**âè¿ä¸ªæ¯è¯ æ¥æä»£ä¸æ°æ®åºäº¤äºçè¿äºç±»åå®ä¾ã + + è Pydantic ä¹ä½¿ç¨â模åâè¿ä¸ªæ¯è¯ æ¥æä»£ä¸åçä¸è¥¿ï¼å³æ°æ®éªè¯ã转æ¢ä»¥åææ¡£ç±»åå®ä¾ã + +ä»`database`ï¼æ¥èªä¸é¢ç`database.py`æä»¶ï¼å¯¼å ¥`Base`ã + +å建ä»å®ç»§æ¿çç±»ã + +è¿äºç±»å°±æ¯ SQLAlchemy 模åã + +```Python hl_lines="4 7-8 18-19" +{!../../../docs_src/sql_databases/sql_app/models.py!} +``` + +è¿ä¸ª`__tablename__`屿§æ¯ç¨æ¥åè¯ SQLAlchemy è¦å¨æ°æ®åºä¸ä¸ºæ¯ä¸ªæ¨¡å使ç¨çæ°æ®åºè¡¨çåç§°ã + +### å建模å屿§/å + +ç°å¨åå»ºæææ¨¡åï¼ç±»ï¼å±æ§ã + +è¿äºå±æ§ä¸çæ¯ä¸ä¸ªé½ä»£è¡¨å ¶ç¸åºæ°æ®åºè¡¨ä¸çä¸åã + +æä»¬ä½¿ç¨`Column`æ¥è¡¨ç¤º SQLAlchemy ä¸çé»è®¤å¼ã + +æä»¬ä¼ éä¸ä¸ª SQLAlchemy âç±»åâï¼å¦`Integer`ã`String`å`Boolean`ï¼å®å®ä¹äºæ°æ®åºä¸çç±»åï¼ä½ä¸ºåæ°ã + +```Python hl_lines="1 10-13 21-24" +{!../../../docs_src/sql_databases/sql_app/models.py!} +``` + +### åå»ºå ³ç³» + +ç°å¨åå»ºå ³ç³»ã + +为æ¤ï¼æä»¬ä½¿ç¨SQLAlchemy ORMæä¾ç`relationship`ã + +è¿å°æå¤æå°ä¼æä¸ºä¸ç§âç¥å¥â屿§ï¼å ¶ä¸è¡¨ç¤ºè¯¥è¡¨ä¸å ¶ä»ç¸å ³ç表ä¸çå¼ã + +```Python hl_lines="2 15 26" +{!../../../docs_src/sql_databases/sql_app/models.py!} +``` + +å½è®¿é® user ä¸ç屿§`items`æ¶ï¼å¦ ä¸`my_user.items`ï¼å®å°æä¸ä¸ª`Item`SQLAlchemy 模ååè¡¨ï¼æ¥èª`items`表ï¼ï¼è¿äºæ¨¡åå ·ææå`users`è¡¨ä¸æ¤è®°å½çå¤é®ã + +彿¨è®¿é®`my_user.items`æ¶ï¼SQLAlchemy å®é ä¸ä¼ä»`items`表ä¸çè·å䏿¹è®°å½å¹¶å¨æ¤å¤å¡«å è¿å»ã + +åæ ·ï¼å½è®¿é® Itemä¸ç屿§`owner`æ¶ï¼å®å°å å«è¡¨ä¸ç`User`SQLAlchemy 模å`users`ã使ç¨`owner_id`屿§/ååå ¶å¤é®æ¥äºè§£è¦ä»`users`表ä¸è·ååªæ¡è®°å½ã + +## å建 Pydantic 模å + +ç°å¨è®©æä»¬æ¥çä¸ä¸æä»¶`sql_app/schemas.py`ã + +!!! tip + 为äºé¿å SQLAlchemy*模å*å Pydantic*模å*ä¹é´çæ··æ·ï¼æä»¬å°æ`models.py`ï¼SQLAlchemy 模åçæä»¶ï¼å`schemas.py`ï¼ Pydantic 模åçæä»¶ï¼ã + + è¿äº Pydantic 模åæå¤æå°å°å®ä¹äºä¸ä¸ªâschemaâï¼ä¸ä¸ªææçæ°æ®å½¢ç¶ï¼ã + + å æ¤ï¼è¿å°å¸®å©æä»¬å¨ä½¿ç¨ä¸¤è æ¶é¿å æ··æ·ã + +### å建åå§ Pydantic*模å*/æ¨¡å¼ + +å建ä¸ä¸ª`ItemBase`å`UserBase`Pydantic*模å*ï¼æè æä»¬è¯´âschemaâï¼ä»¥åå¨å建æè¯»åæ°æ®æ¶å ·æå ±åç屿§ã + +`ItemCreate`为 å建ä¸ä¸ª`UserCreate`ç»§æ¿èªå®ä»¬çææå±æ§ï¼å æ¤å®ä»¬å°å ·æç¸åç屿§ï¼ï¼ä»¥åå建æéçä»»ä½å ¶ä»æ°æ®ï¼å±æ§ï¼ã + +å æ¤å¨å建æ¶ä¹åºå½æä¸ä¸ª`password`屿§ã + +使¯ä¸ºäºå®å ¨èµ·è§ï¼`password`ä¸ä¼åºç°å¨å ¶ä»åç±» Pydantic*模å*ä¸ï¼ä¾å¦ç¨æ·è¯·æ±æ¶ä¸åºè¯¥ä» API è¿åååºä¸å å«å®ã + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="3 6-8 11-12 23-24 27-28" + {!> ../../../docs_src/sql_databases/sql_app/schemas.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="3 6-8 11-12 23-24 27-28" + {!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!} + ``` + +=== "Python 3.10 å以ä¸çæ¬" + + ```Python hl_lines="1 4-6 9-10 21-22 25-26" + {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!} + ``` + +#### SQLAlchemy 飿 ¼å Pydantic 飿 ¼ + +请注æï¼SQLAlchemy*模å*ä½¿ç¨ `=`æ¥å®ä¹å±æ§ï¼å¹¶å°ç±»åä½ä¸ºåæ°ä¼ éç»`Column`ï¼ä¾å¦ï¼ + +```Python +name = Column(String) +``` + +è½ç¶ Pydantic*模å*使ç¨`:` 声æç±»åï¼ä½æ°çç±»åæ³¨éè¯æ³/ç±»åæç¤ºæ¯ï¼ + +```Python +name: str +``` + +请ç¢è®°è¿ä¸ç¹ï¼è¿æ ·æ¨å¨ä½¿ç¨`:`è¿æ¯`=`æ¶å°±ä¸ä¼æå°å°æã + +### å建ç¨äºè¯»å/è¿åçPydantic*模å/模å¼* + +ç°å¨å建å½ä» API è¿åæ°æ®æ¶ãå°å¨è¯»åæ°æ®æ¶ä½¿ç¨çPydantic*模åï¼schemasï¼ã* + +ä¾å¦ï¼å¨å建ä¸ä¸ªé¡¹ç®ä¹åï¼æä»¬ä¸ç¥éåé ç»å®ç ID æ¯ä»ä¹ï¼ä½æ¯å¨è¯»å宿¶ï¼ä» API è¿åæ¶ï¼æä»¬å·²ç»ç¥éå®ç IDã + +åæ ·ï¼å½è¯»åç¨æ·æ¶ï¼æä»¬ç°å¨å¯ä»¥å£°æ`items`ï¼å°å å«å±äºè¯¥ç¨æ·ç项ç®ã + +ä¸ä» æ¯è¿äºé¡¹ç®ç IDï¼è¿ææä»¬å¨ Pydantic*模å*ä¸å®ä¹çç¨äºè¯»å项ç®çæææ°æ®ï¼`Item`. + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="15-17 31-34" + {!> ../../../docs_src/sql_databases/sql_app/schemas.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="15-17 31-34" + {!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!} + ``` + +=== "Python 3.10 å以ä¸çæ¬" + + ```Python hl_lines="13-15 29-32" + {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!} + ``` + +!!! tip + 请注æï¼è¯»åç¨æ·ï¼ä» API è¿åï¼æ¶å°ä½¿ç¨ä¸å æ¬`password`ç`User` Pydantic*模å*ã + +### ä½¿ç¨ Pydantic ç`orm_mode` + +ç°å¨ï¼å¨ç¨äºæ¥è¯¢ç Pydantic*模å*`Item`ä¸`User`ï¼æ·»å ä¸ä¸ªå é¨`Config`ç±»ã + +æ¤ç±»[`Config`](https://pydantic-docs.helpmanual.io/usage/model_config/)ç¨äºä¸º Pydantic æä¾é ç½®ã + +å¨`Config`ç±»ä¸ï¼è®¾ç½®å±æ§`orm_mode = True`ã + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="15 19-20 31 36-37" + {!> ../../../docs_src/sql_databases/sql_app/schemas.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="15 19-20 31 36-37" + {!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!} + ``` + +=== "Python 3.10 å以ä¸çæ¬" + + ```Python hl_lines="13 17-18 29 34-35" + {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!} + ``` + +!!! tip + 请注æï¼å®ä½¿ç¨`=`åé ä¸ä¸ªå¼ï¼ä¾å¦ï¼ + + `orm_mode = True` + + å®ä¸ä½¿ç¨ä¹åç`:`æ¥ç±»å声æã + + è¿æ¯è®¾ç½®é ç½®å¼ï¼è䏿¯å£°æç±»åã + +Pydantic`orm_mode`å°åè¯ Pydantic*模å*è¯»åæ°æ®ï¼å³å®ä¸æ¯ä¸ä¸ª`dict`ï¼èæ¯ä¸ä¸ª ORM 模åï¼æä»»ä½å ¶ä»å ·æå±æ§çä»»æå¯¹è±¡ï¼ã + +è¿æ ·ï¼è䏿¯ä» ä» è¯å¾ä»`dict`ä¸ `id` ä¸è·åå¼ï¼å¦ä¸æç¤ºï¼ + +```Python +id = data["id"] +``` + +å°è¯ä»å±æ§ä¸è·åå®ï¼å¦ï¼ + +```Python +id = data.id +``` + +æäºè¿ä¸ªï¼Pydantic*模å*ä¸ ORM å ¼å®¹ï¼æ¨åªéå¨*è·¯å¾æä½*`response_model`çåæ°ä¸å£°æå®å³å¯ã + +æ¨å°è½å¤è¿åä¸ä¸ªæ°æ®åºæ¨¡åï¼å®å°ä»ä¸è¯»åæ°æ®ã + +#### ORM 模å¼çææ¯ç»è + +SQLAlchemy å许å¤å ¶ä»é»è®¤æ åµä¸æ¯âå»¶è¿å è½½âã + +è¿æå³çï¼ä¾å¦ï¼é¤éæ¨å°è¯è®¿é®å å«è¯¥æ°æ®ç屿§ï¼å¦åå®ä»¬ä¸ä¼ä»æ°æ®åºä¸è·åå ³ç³»æ°æ®ã + +ä¾å¦ï¼è®¿é®å±æ§`items`ï¼ + +```Python +current_user.items +``` + +å°ä½¿ SQLAlchemy 转å°`items`表并è·åè¯¥ç¨æ·ç项ç®ï¼å¨è°ç¨`.items`ä¹åä¸ä¼å»æ¥è¯¢æ°æ®åºã + +没æ`orm_mode`ï¼å¦ææ¨ä»*è·¯å¾æä½*è¿åä¸ä¸ª SQLAlchemy 模åï¼å®ä¸ä¼å å«å ³ç³»æ°æ®ã + +å³ä½¿æ¨å¨ Pydantic 模åä¸å£°æäºè¿äºå ³ç³»ï¼ä¹æ²¡æç¨å¤ã + +使¯å¨ ORM 模å¼ä¸ï¼ç±äº Pydantic æ¬èº«ä¼å°è¯ä»å±æ§è®¿é®å®éè¦çæ°æ®ï¼è䏿¯å设为 `dict`ï¼ï¼ä½ å¯ä»¥å£°æä½ æ³è¦è¿åçç¹å®æ°æ®ï¼å®çè³å¯ä»¥ä» ORM ä¸è·åå®ã + +## CRUDå·¥å · + +ç°å¨è®©æä»¬ççæä»¶`sql_app/crud.py`ã + +å¨è¿ä¸ªæä»¶ä¸ï¼æä»¬å°ç¼åå¯éç¨ç彿°ç¨æ¥ä¸æ°æ®åºä¸çæ°æ®è¿è¡äº¤äºã + +**CRUD**åå«ä¸ºï¼**å¢å **ã**æ¥è¯¢**ã**æ´æ¹**å**å é¤**ï¼å³å¢å æ¹æ¥ã + +...è½ç¶å¨è¿ä¸ªä¾åä¸æä»¬åªæ¯æ°å¢åæ¥è¯¢ã + +### è¯»åæ°æ® + +ä» `sqlalchemy.orm`ä¸å¯¼å ¥`Session`ï¼è¿å°å 许æ¨å£°æ`db`åæ°çç±»åï¼å¹¶å¨æ¨ç彿°ä¸è¿è¡æ´å¥½çç±»åæ£æ¥å宿ã + +å¯¼å ¥ä¹åç`models`ï¼SQLAlchemy 模åï¼å`schemas`ï¼Pydantic*模å*/模å¼ï¼ã + +å建ä¸äºå®ç¨å½æ°æ¥å®æï¼ + +* éè¿ ID åçµåé®ä»¶æ¥è¯¢åä¸ªç¨æ·ã +* æ¥è¯¢å¤ä¸ªç¨æ·ã +* æ¥è¯¢å¤ä¸ªé¡¹ç®ã + +```Python hl_lines="1 3 6-7 10-11 14-15 27-28" +{!../../../docs_src/sql_databases/sql_app/crud.py!} +``` + +!!! tip + éè¿åå»ºä» ä¸ç¨äºä¸æ°æ®åºäº¤äºï¼è·åç¨æ·æé¡¹ç®ï¼ç彿°ï¼ç¬ç«äº*è·¯å¾æä½å½æ°*ï¼æ¨å¯ä»¥æ´è½»æ¾å°å¨å¤ä¸ªé¨åä¸éç¨å®ä»¬ï¼å¹¶ä¸ºå®ä»¬æ·»å åå æµè¯ã + +### åå»ºæ°æ® + +ç°å¨å建å®ç¨ç¨åºå½æ°æ¥åå»ºæ°æ®ã + +å®çæ¥éª¤æ¯ï¼ + +* ä½¿ç¨æ¨çæ°æ®å建ä¸ä¸ª SQLAlchemy 模å*å®ä¾ã* +* 使ç¨`add`æ¥å°è¯¥å®ä¾å¯¹è±¡æ·»å å°æ¨çæ°æ®åºã +* 使ç¨`commit`æ¥å¯¹æ°æ®åºçäºå¡æäº¤ï¼ä»¥ä¾¿ä¿åå®ä»¬ï¼ã +* 使ç¨`refresh`æ¥å·æ°æ¨çæ°æ®åºå®ä¾ï¼ä»¥ä¾¿å®å 嫿¥èªæ°æ®åºç任使°æ°æ®ï¼ä¾å¦çæç IDï¼ã + +```Python hl_lines="18-24 31-36" +{!../../../docs_src/sql_databases/sql_app/crud.py!} +``` + +!!! tip + SQLAlchemy 模å`User`å å«ä¸ä¸ª`hashed_password`ï¼å®åºè¯¥æ¯ä¸ä¸ªå 嫿£åçå®å ¨å¯ç ã + + ä½ç±äº API 客æ·ç«¯æä¾çæ¯åå§å¯ç ï¼å æ¤æ¨éè¦å°å ¶æåå¹¶å¨åºç¨ç¨åºä¸çææ£åå¯ç ã + + ç¶åå°hashed_passwordåæ°ä¸è¦ä¿åçå¼ä¸èµ·ä¼ éã + +!!! warning + æ¤ç¤ºä¾ä¸å®å ¨ï¼å¯ç æªç»è¿åå¸å¤çã + + å¨ç°å®çæ´»ä¸çåºç¨ç¨åºä¸ï¼æ¨éè¦å¯¹å¯ç è¿è¡åå¸å¤çï¼å¹¶ä¸æ°¸è¿ä¸è¦ä»¥ææå½¢å¼ä¿åå®ä»¬ã + + æå ³æ´å¤è¯¦ç»ä¿¡æ¯ï¼è¯·è¿åæç¨ä¸çå®å ¨é¨åã + + å¨è¿éï¼æä»¬åªå ³æ³¨æ°æ®åºçå·¥å ·åæºå¶ã + +!!! tip + è¿é䏿¯å°æ¯ä¸ªå ³é®ååæ°ä¼ éç»Itemå¹¶ä»Pydantic模åä¸è¯»åæ¯ä¸ªåæ°ï¼èæ¯å çæä¸ä¸ªåå ¸ï¼å ¶ä¸å å«Pydantic模åçæ°æ®ï¼ + + `item.dict()` + + ç¶åæä»¬å°dictçé®å¼å¯¹ ä½ä¸ºå ³é®ååæ°ä¼ éç» SQLAlchemy `Item`ï¼ + + `Item(**item.dict())` + + ç¶åæä»¬ä¼ é Pydanticæ¨¡åæªæä¾çé¢å¤å ³é®ååæ°`owner_id`ï¼ + + `Item(**item.dict(), owner_id=user_id)` + +## 主**FastAPI**åºç¨ç¨åº + +ç°å¨å¨`sql_app/main.py`æä»¶ä¸ 让æä»¬éæåä½¿ç¨æä»¬ä¹ååå»ºçææå ¶ä»é¨åã + +### åå»ºæ°æ®åºè¡¨ + +以é常ç®åçæ¹å¼åå»ºæ°æ®åºè¡¨ï¼ + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="9" + {!> ../../../docs_src/sql_databases/sql_app/main.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="7" + {!> ../../../docs_src/sql_databases/sql_app_py39/main.py!} + ``` + +#### Alembic 注æ + +éå¸¸ä½ å¯è½ä¼ä½¿ç¨ Alembicï¼æ¥è¿è¡æ ¼å¼åæ°æ®åºï¼å建表çï¼ã + +è䏿¨è¿å¯ä»¥å° Alembic ç¨äºâè¿ç§»âï¼è¿æ¯å®ç主è¦å·¥ä½ï¼ã + +âè¿ç§»âæ¯æ¯å½æ¨æ´æ¹ SQLAlchemy 模åçç»æãæ·»å æ°å±æ§ç以卿°æ®åºä¸å¤å¶è¿äºæ´æ¹ãæ·»å æ°åãæ°è¡¨çæ¶æéçä¸ç»æ¥éª¤ã + +æ¨å¯ä»¥å¨[Project Generation - Template](https://fastapi.tiangolo.com/zh/project-generation/)çæ¨¡æ¿ä¸æ¾å°ä¸ä¸ª FastAPI 项ç®ä¸ç Alembic 示ä¾ãå ·ä½å¨[`alembic`代ç ç®å½ä¸](https://github.com/tiangolo/full-stack-fastapi-postgresql/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/alembic/)ã + +### å建ä¾èµé¡¹ + +ç°å¨ä½¿ç¨æä»¬å¨`sql_app/database.py`æä»¶ä¸å建ç`SessionLocal`æ¥å建ä¾èµé¡¹ã + +æä»¬éè¦æ¯ä¸ªè¯·æ±æä¸ä¸ªç¬ç«çæ°æ®åºä¼è¯/è¿æ¥ï¼`SessionLocal`ï¼ï¼å¨ææè¯·æ±ä¸ä½¿ç¨ç¸åçä¼è¯ï¼ç¶åå¨è¯·æ±å®æåå ³éå®ã + +ç¶åå°ä¸ºä¸ä¸ä¸ªè¯·æ±å建ä¸ä¸ªæ°ä¼è¯ã + +为æ¤ï¼æä»¬å°å建ä¸ä¸ªæ°çä¾èµé¡¹`yield`ï¼æ£å¦åé¢å ³äº[Dependencies with`yield`](https://fastapi.tiangolo.com/zh/tutorial/dependencies/dependencies-with-yield/)çé¨åä¸æè§£éç飿 ·ã + +æä»¬çä¾èµé¡¹å°å建ä¸ä¸ªæ°ç SQLAlchemy `SessionLocal`ï¼å®å°å¨å个请æ±ä¸ä½¿ç¨ï¼ç¶åå¨è¯·æ±å®æåå ³éå®ã + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="15-20" + {!> ../../../docs_src/sql_databases/sql_app/main.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="13-18" + {!> ../../../docs_src/sql_databases/sql_app_py39/main.py!} + ``` + +!!! info + æä»¬å°`SessionLocal()`请æ±çå建åå¤çæ¾å¨ä¸ä¸ª`try`åä¸ã + + ç¶åæä»¬å¨finallyåä¸å ³éå®ã + + éè¿è¿ç§æ¹å¼ï¼æä»¬ç¡®ä¿æ°æ®åºä¼è¯å¨è¯·æ±åå§ç»å ³éãå³ä½¿å¨å¤çè¯·æ±æ¶åºç°å¼å¸¸ã + + 使¯æ¨ä¸è½ä»éåºä»£ç ä¸å¼åå¦ä¸ä¸ªå¼å¸¸ï¼å¨yieldä¹åï¼ãå¯ä»¥æ¥é [Dependencies with yield and HTTPException](https://fastapi.tiangolo.com/zh/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-httpexception) + +*ç¶åï¼å½å¨è·¯å¾æä½å½æ°*ä¸ä½¿ç¨ä¾èµé¡¹æ¶ï¼æä»¬ä½¿ç¨`Session`ï¼ç´æ¥ä» SQLAlchemy å¯¼å ¥çç±»å声æå®ã + +*è¿å°ä¸ºæä»¬å¨è·¯å¾æä½å½æ°*䏿便´å¥½çç¼è¾å¨æ¯æï¼å 为ç¼è¾å¨å°ç¥é`db`åæ°çç±»å`Session`ï¼ + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="24 32 38 47 53" + {!> ../../../docs_src/sql_databases/sql_app/main.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="22 30 36 45 51" + {!> ../../../docs_src/sql_databases/sql_app_py39/main.py!} + ``` + +!!! info "ææ¯ç»è" + åæ°`db`å®é 䏿¯ type `SessionLocal`ï¼ä½æ¯è¿ä¸ªç±»ï¼ç¨ å建`sessionmaker()`ï¼æ¯ SQLAlchemy çâ代çâ `Session`ï¼æä»¥ï¼ç¼è¾å¨å¹¶ä¸çæ£ç¥éæä¾äºåªäºæ¹æ³ã + + 使¯éè¿å°ç±»å声æä¸ºSessionï¼ç¼è¾å¨ç°å¨å¯ä»¥ç¥éå¯ç¨çæ¹æ³ï¼.add()ã.query()ã.commit()çï¼å¹¶ä¸å¯ä»¥æä¾æ´å¥½çæ¯æï¼æ¯å¦å®æï¼ãç±»å声æä¸å½±åå®é 对象ã + +### å建æ¨ç**FastAPI** *è·¯å¾æä½* + +ç°å¨ï¼å°äºæåï¼ç¼åæ åç**FastAPI** *è·¯å¾æä½*代ç ã + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python hl_lines="23-28 31-34 37-42 45-49 52-55" + {!> ../../../docs_src/sql_databases/sql_app/main.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python hl_lines="21-26 29-32 35-40 43-47 50-53" + {!> ../../../docs_src/sql_databases/sql_app_py39/main.py!} + ``` + +æä»¬å¨ä¾èµé¡¹ä¸çæ¯ä¸ªè¯·æ±ä¹åå©ç¨`yield`åå»ºæ°æ®åºä¼è¯ï¼ç¶åå ³éå®ã + +æä»¥æä»¬å°±å¯ä»¥å¨*è·¯å¾æä½å½æ°*ä¸å建éè¦çä¾èµï¼å°±è½ç´æ¥è·åä¼è¯ã + +è¿æ ·ï¼æä»¬å°±å¯ä»¥ç´æ¥ä»*è·¯å¾æä½å½æ°*å é¨è°ç¨`crud.get_user`并使ç¨è¯¥ä¼è¯ï¼æ¥è¿è¡å¯¹æ°æ®åºæä½ã + +!!! tip + 请注æï¼æ¨è¿åç弿¯ SQLAlchemy æ¨¡åæ SQLAlchemy 模åå表ã + + 使¯ç±äºææè·¯å¾æä½çresponse_modelé½ä½¿ç¨ Pydantic模å/使ç¨orm_mode模å¼ï¼å æ¤æ¨ç Pydantic 模åä¸å£°æçæ°æ®å°ä»å®ä»¬ä¸æåå¹¶è¿åç»å®¢æ·ç«¯ï¼å¹¶è¿è¡æææ£å¸¸çè¿æ»¤åéªè¯ã + +!!! tip + å¦è¯·æ³¨æï¼`response_models`åºå½æ¯æ å Python ç±»åï¼ä¾å¦`List[schemas.Item]`. + + 使¯ç±äºå®çå 容/åæ°Listæ¯ä¸ä¸ª 使ç¨orm_mode模å¼çPydantic模åï¼æä»¥æ°æ®å°è¢«æ£å¸¸æ£ç´¢å¹¶è¿åç»å®¢æ·ç«¯ï¼æä»¥æ²¡æé®é¢ã + +### å ³äº `def` å¯¹æ¯ `async def` + +*å¨è¿éï¼æä»¬å¨è·¯å¾æä½å½æ°*åä¾èµé¡¹ä¸é½ä½¿ç¨ç SQLAlchemy 模åï¼å®å°ä¸å¤é¨æ°æ®åºè¿è¡éä¿¡ã + +è¿ä¼éè¦ä¸äºâçå¾ æ¶é´âã + +使¯ç±äº SQLAlchemy ä¸å ·æ`await`ç´æ¥ä½¿ç¨çå ¼å®¹æ§ï¼å æ¤ç±»ä¼¼äºï¼ + +```Python +user = await db.query(User).first() +``` + +...ç¸åï¼æä»¬å¯ä»¥ä½¿ç¨ï¼ + +```Python +user = db.query(User).first() +``` + +ç¶åæä»¬åºè¯¥å£°æ*è·¯å¾æä½å½æ°*åä¸å¸¦ çä¾èµå ³ç³»`async def`ï¼åªéä½¿ç¨æ®éç`def`ï¼å¦ä¸ï¼ + +```Python hl_lines="2" +@app.get("/users/{user_id}", response_model=schemas.User) +def read_user(user_id: int, db: Session = Depends(get_db)): + db_user = crud.get_user(db, user_id=user_id) + ... +``` + +!!! info + 妿æ¨éè¦å¼æ¥è¿æ¥å°å ³ç³»æ°æ®åºï¼è¯·åé [Async SQL (Relational) Databases](https://fastapi.tiangolo.com/zh/advanced/async-sql-databases/) + +!!! note "Very Technical Details" + 妿æ¨å¾å¥½å¥å¹¶ä¸æ¥ææ·±åçææ¯ç¥è¯ï¼æ¨å¯ä»¥å¨[Async](https://fastapi.tiangolo.com/zh/async/#very-technical-details)ææ¡£ä¸æ¥çæå ³å¦ä½å¤ç `async def`äº`def`å·®å«çææ¯ç»èã + +## è¿ç§» + +å 为æä»¬ç´æ¥ä½¿ç¨ SQLAlchemyï¼å¹¶ä¸æä»¬ä¸éè¦ä»»ä½ç±»åçæä»¶æ¥ä½¿ç¨**FastAPI**ï¼æä»¥æä»¬å¯ä»¥ç´æ¥å°æ°æ®åºè¿ç§»è³[Alembic](https://alembic.sqlalchemy.org/)è¿è¡éæã + +ç±äºä¸ SQLAlchemy å SQLAlchemy 模åç¸å ³ç代ç ä½äºåç¬çç¬ç«æä»¶ä¸ï¼æ¨çè³å¯ä»¥ä½¿ç¨ Alembic æ§è¡è¿ç§»ï¼èæ éå®è£ FastAPIãPydantic æå ¶ä»ä»»ä½ä¸è¥¿ã + +åæ ·ï¼æ¨å°è½å¤å¨ä¸**FastAPI**æ å ³ç代ç çå ¶ä»é¨åä¸ä½¿ç¨ç¸åç SQLAlchemy 模ååå®ç¨ç¨åºã + +ä¾å¦ï¼å¨å ·æ[Celery](https://docs.celeryq.dev/)ã[RQ](https://python-rq.org/)æ[ARQ](https://arq-docs.helpmanual.io/)çåå°ä»»å¡å·¥ä½è ä¸ã + +## å®¡æ¥æææä»¶ + +æåå顾æ´ä¸ªæ¡ä¾ï¼æ¨åºè¯¥æä¸ä¸ªå为çç®å½`my_super_project`ï¼å ¶ä¸å å«ä¸ä¸ªå为`sql_app`ã + +`sql_app`ä¸åºè¯¥æä»¥ä¸æä»¶ï¼ + +* `sql_app/__init__.py`ï¼è¿æ¯ä¸ä¸ªç©ºæä»¶ã + +* `sql_app/database.py`ï¼ + +```Python +{!../../../docs_src/sql_databases/sql_app/database.py!} +``` + +* `sql_app/models.py`: + +```Python +{!../../../docs_src/sql_databases/sql_app/models.py!} +``` + +* `sql_app/schemas.py`: + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python + {!> ../../../docs_src/sql_databases/sql_app/schemas.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python + {!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!} + ``` + +=== "Python 3.10 å以ä¸çæ¬" + + ```Python + {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!} + ``` + +* `sql_app/crud.py`: + +```Python +{!../../../docs_src/sql_databases/sql_app/crud.py!} +``` + +* `sql_app/main.py`: + +=== "Python 3.6 å以ä¸çæ¬" + + ```Python + {!> ../../../docs_src/sql_databases/sql_app/main.py!} + ``` + +=== "Python 3.9 å以ä¸çæ¬" + + ```Python + {!> ../../../docs_src/sql_databases/sql_app_py39/main.py!} + ``` + +## æ§è¡é¡¹ç® + +æ¨å¯ä»¥å¤å¶è¿äºä»£ç å¹¶æåæ ·ä½¿ç¨å®ã + +!!! info + + äºå®ä¸ï¼è¿éç代ç åªæ¯å¤§å¤æ°æµè¯ä»£ç çä¸é¨åã + +ä½ å¯ä»¥ç¨ Uvicorn è¿è¡å®ï¼ + + +