Skip to content

๐Ÿ” ๐Ÿ—„ (๐Ÿ”—) ๐Ÿ’ฝ

๐Ÿ‘† ๐Ÿ’ช โš™๏ธ encode/databases โฎ๏ธ FastAPI ๐Ÿ”— ๐Ÿ’ฝ โš™๏ธ async & await.

โšซ๏ธ ๐Ÿ”— โฎ๏ธ:

  • โœณ
  • โœณ
  • ๐Ÿ—„

๐Ÿ‘‰ ๐Ÿ–ผ, ๐Ÿ‘ฅ ๐Ÿ”œ โš™๏ธ ๐Ÿ—„, โ†ฉ๏ธ โšซ๏ธ โš™๏ธ ๐Ÿ‘ ๐Ÿ“ & ๐Ÿ โœ”๏ธ ๐Ÿ› ๏ธ ๐Ÿ•โ€๐Ÿฆบ. , ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“ ๐Ÿ‘‰ ๐Ÿ–ผ & ๐Ÿƒ โšซ๏ธ.

โช, ๐Ÿ‘† ๐Ÿญ ๐Ÿˆธ, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ’š โš™๏ธ ๐Ÿ’ฝ ๐Ÿ’ฝ ๐Ÿ’– โœณ.

Tip

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ› ๏ธ ๐Ÿ’ญ โšช๏ธโžก๏ธ ๐Ÿ“„ ๐Ÿ”ƒ ๐Ÿ‡ธ๐Ÿ‡ฒ ๐Ÿœ (๐Ÿ—„ (๐Ÿ”—) ๐Ÿ’ฝ), ๐Ÿ’– โš™๏ธ ๐Ÿš™ ๐Ÿ”ข ๐ŸŽญ ๐Ÿ› ๏ธ ๐Ÿ’ฝ, ๐Ÿ”ฌ ๐Ÿ‘† FastAPI ๐Ÿ“Ÿ.

๐Ÿ‘‰ ๐Ÿ“„ ๐Ÿšซ โœ” ๐Ÿ“š ๐Ÿ’ญ, ๐ŸŒ“ ๐Ÿ˜‘ ๐Ÿ’ƒ.

๐Ÿ—„ & โš’ ๐Ÿ†™ SQLAlchemy

  • ๐Ÿ—„ SQLAlchemy.
  • โœ metadata ๐ŸŽš.
  • โœ ๐Ÿ“ notes โš™๏ธ metadata ๐ŸŽš.
from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

Tip

๐Ÿ‘€ ๐Ÿ‘ˆ ๐ŸŒ ๐Ÿ‘‰ ๐Ÿ“Ÿ ๐Ÿ˜ ๐Ÿ‡ธ๐Ÿ‡ฒ ๐Ÿš.

databases ๐Ÿšซ ๐Ÿ”จ ๐Ÿ•ณ ๐Ÿ“ฅ.

๐Ÿ—„ & โš’ ๐Ÿ†™ databases

  • ๐Ÿ—„ databases.
  • โœ DATABASE_URL.
  • โœ database ๐ŸŽš.
from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

Tip

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ”— ๐ŸŽ ๐Ÿ’ฝ (โœ… โœณ), ๐Ÿ‘† ๐Ÿ”œ ๐Ÿ’ช ๐Ÿ”€ DATABASE_URL.

โœ ๐Ÿ“

๐Ÿ‘‰ ๐Ÿ’ผ, ๐Ÿ‘ฅ ๐Ÿ— ๐Ÿ“ ๐ŸŽ ๐Ÿ ๐Ÿ“, โœ‹๏ธ ๐Ÿญ, ๐Ÿ‘† ๐Ÿ”œ ๐ŸŽฒ ๐Ÿ’š โœ ๐Ÿ‘ซ โฎ๏ธ โš—, ๐Ÿ› ๏ธ โฎ๏ธ ๐Ÿ› ๏ธ, โ™’๏ธ.

๐Ÿ“ฅ, ๐Ÿ‘‰ ๐Ÿ“„ ๐Ÿ”œ ๐Ÿƒ ๐Ÿ”—, โ–ถ๏ธ๏ธ โญ โ–ถ๏ธ ๐Ÿ‘† FastAPI ๐Ÿˆธ.

  • โœ engine.
  • โœ ๐ŸŒ ๐Ÿ“ โšช๏ธโžก๏ธ metadata ๐ŸŽš.
from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

โœ ๐Ÿท

โœ Pydantic ๐Ÿท:

  • ๐Ÿ—’ โœ (NoteIn).
  • ๐Ÿ—’ ๐Ÿ“จ (Note).
from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

๐Ÿ— ๐Ÿ‘ซ Pydantic ๐Ÿท, ๐Ÿ”ข ๐Ÿ’ฝ ๐Ÿ”œ โœ”, ๐ŸŽป (๐Ÿ—œ), & โœ (๐Ÿ“„).

, ๐Ÿ‘† ๐Ÿ”œ ๐Ÿ’ช ๐Ÿ‘€ โšซ๏ธ ๐ŸŒ ๐ŸŽ“ ๐Ÿ› ๏ธ ๐Ÿฉบ.

๐Ÿ”— & ๐Ÿ”Œ

  • โœ ๐Ÿ‘† FastAPI ๐Ÿˆธ.
  • โœ ๐ŸŽ‰ ๐Ÿ•โ€๐Ÿฆบ ๐Ÿ”— & ๐Ÿ”Œ โšช๏ธโžก๏ธ ๐Ÿ’ฝ.
from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

โœ ๐Ÿ—’

โœ โžก ๐Ÿ› ๏ธ ๐Ÿ”ข โœ ๐Ÿ—’:

from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

Note

๐Ÿ‘€ ๐Ÿ‘ˆ ๐Ÿ‘ฅ ๐Ÿ”— โฎ๏ธ ๐Ÿ’ฝ โš™๏ธ await, โžก ๐Ÿ› ๏ธ ๐Ÿ”ข ๐Ÿ“ฃ โฎ๏ธ async.

๐Ÿ‘€ response_model=List[Note]

โšซ๏ธ โš™๏ธ typing.List.

๐Ÿ‘ˆ ๐Ÿ“„ (& โœ”, ๐ŸŽป, โ›ฝ) ๐Ÿ”ข ๐Ÿ’ฝ, list Noteโ“‚.

โœ ๐Ÿ—’

โœ โžก ๐Ÿ› ๏ธ ๐Ÿ”ข โœ ๐Ÿ—’:

from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./test.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "notes",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)


engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)


class NoteIn(BaseModel):
    text: str
    completed: bool


class Note(BaseModel):
    id: int
    text: str
    completed: bool


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get("/notes/", response_model=List[Note])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)


@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
    query = notes.insert().values(text=note.text, completed=note.completed)
    last_record_id = await database.execute(query)
    return {**note.dict(), "id": last_record_id}

Note

๐Ÿ‘€ ๐Ÿ‘ˆ ๐Ÿ‘ฅ ๐Ÿ”— โฎ๏ธ ๐Ÿ’ฝ โš™๏ธ await, โžก ๐Ÿ› ๏ธ ๐Ÿ”ข ๐Ÿ“ฃ โฎ๏ธ async.

๐Ÿ”ƒ {**note.dict(), "id": last_record_id}

note Pydantic Note ๐ŸŽš.

note.dict() ๐Ÿ“จ dict โฎ๏ธ ๐Ÿšฎ ๐Ÿ’ฝ, ๐Ÿ•ณ ๐Ÿ’–:

{
    "text": "Some note",
    "completed": False,
}

โœ‹๏ธ โšซ๏ธ ๐Ÿšซ โœ”๏ธ id ๐Ÿ‘.

๐Ÿ‘ฅ โœ ๐Ÿ†• dict, ๐Ÿ‘ˆ ๐Ÿ”Œ ๐Ÿ”‘-๐Ÿ’ฒ ๐Ÿ‘ซ โšช๏ธโžก๏ธ note.dict() โฎ๏ธ:

{**note.dict()}

**note.dict() "unpacks" the key value pairs directly, so, {**note.dict()} would be, more or less, a copy of note.dict().

& โคด๏ธ, ๐Ÿ‘ฅ โ†” ๐Ÿ‘ˆ ๐Ÿ“ dict, โŽ โž•1๏ธโƒฃ ๐Ÿ”‘-๐Ÿ’ฒ ๐Ÿ‘ซ: "id": last_record_id:

{**note.dict(), "id": last_record_id}

, ๐Ÿ ๐Ÿ ๐Ÿ“จ ๐Ÿ”œ ๐Ÿ•ณ ๐Ÿ’–:

{
    "id": 1,
    "text": "Some note",
    "completed": False,
}

โœ… โšซ๏ธ

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“ ๐Ÿ‘‰ ๐Ÿ“Ÿ, & ๐Ÿ‘€ ๐Ÿฉบ http://127.0.0.1:8000/docs.

๐Ÿ“ค ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ‘€ ๐ŸŒ ๐Ÿ‘† ๐Ÿ› ๏ธ ๐Ÿ“„ & ๐Ÿ”— โฎ๏ธ โšซ๏ธ:

๐ŸŒ… โ„น

๐Ÿ‘† ๐Ÿ’ช โœ ๐ŸŒ… ๐Ÿ”ƒ encode/databases ๐Ÿšฎ ๐Ÿ“‚ ๐Ÿ“ƒ.