Skip to content

โ˜ (๐Ÿ“Ž / ๐Ÿฆ ๐Ÿ’ฝ) ๐Ÿ’ฝ

FastAPI ๐Ÿ’ช ๐Ÿ› ๏ธ โฎ๏ธ ๐Ÿ™† โ˜.

๐Ÿ“ฅ ๐Ÿ‘ฅ ๐Ÿ”œ ๐Ÿ‘€ ๐Ÿ–ผ โš™๏ธ ๐Ÿ—„, ๐Ÿ“„ ๐Ÿงข โ˜ ๐Ÿ’ฝ.

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ› ๏ธ โšซ๏ธ ๐Ÿ™† ๐ŸŽ โ˜ ๐Ÿ’ฝ ๐Ÿ’–:

  • โœณ
  • ๐Ÿ‘ธ
  • โœณ
  • ๐Ÿ‡ธ๐Ÿ‡ฒ
  • โœณ, โ™’๏ธ.

Tip

๐Ÿ“ค ๐Ÿ›‚ ๐Ÿ— ๐Ÿš‚ โฎ๏ธ FastAPI & ๐Ÿ—„, ๐ŸŒ โš“๏ธ ๐Ÿ”› โ˜, ๐Ÿ”Œ ๐Ÿ•ธ & ๐ŸŒ– ๐Ÿงฐ: https://github.com/tiangolo/full-stack-fastapi-couchbase

๐Ÿ—„ ๐Ÿ—„ ๐Ÿฆฒ

๐Ÿ”œ, ๐Ÿšซ ๐Ÿ’ธ ๐Ÿ™‹ ๐ŸŽ‚, ๐Ÿ•ด ๐Ÿ—„:

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

๐Ÿ”ฌ ๐Ÿ“‰ โš™๏ธ "๐Ÿ“„ ๐Ÿ†Ž"

๐Ÿ‘ฅ ๐Ÿ”œ โš™๏ธ โšซ๏ธ โช ๐Ÿ”ง ๐Ÿ‘ type ๐Ÿ‘† ๐Ÿ“„.

๐Ÿ‘‰ ๐Ÿšซ โœ” ๐Ÿ—„, โœ‹๏ธ ๐Ÿ‘ ๐Ÿ’ก ๐Ÿ‘ˆ ๐Ÿ”œ โ„น ๐Ÿ‘† โฎ๏ธ.

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

๐Ÿšฎ ๐Ÿ”ข ๐Ÿคš Bucket

๐Ÿ—„, ๐Ÿฅก โš’ ๐Ÿ“„, ๐Ÿ‘ˆ ๐Ÿ’ช ๐ŸŽ ๐Ÿ†Ž.

๐Ÿ‘ซ ๐Ÿ›Ž ๐ŸŒ ๐Ÿ”— ๐ŸŽ ๐Ÿˆธ.

๐Ÿ”‘ ๐Ÿ”— ๐Ÿ’ฝ ๐ŸŒ ๐Ÿ”œ "๐Ÿ’ฝ" (๐ŸŽฏ ๐Ÿ’ฝ, ๐Ÿšซ ๐Ÿ’ฝ ๐Ÿ’ฝ).

๐Ÿ”‘ โœณ ๐Ÿ”œ "๐Ÿ—ƒ".

๐Ÿ“Ÿ, Bucket ๐ŸŽจ ๐Ÿ‘‘ ๐Ÿ‡จ๐Ÿ‡ป ๐Ÿ“ป โฎ๏ธ ๐Ÿ’ฝ.

๐Ÿ‘‰ ๐Ÿš™ ๐Ÿ”ข ๐Ÿ”œ:

  • ๐Ÿ”— ๐Ÿ—„ ๐ŸŒ‘ (๐Ÿ‘ˆ ๐Ÿ’ช ๐Ÿ‘ ๐ŸŽฐ).
    • โš’ ๐Ÿ”ข โฒ.
  • ๐Ÿ”“ ๐ŸŒ‘.
  • ๐Ÿคš Bucket ๐Ÿ‘.
    • โš’ ๐Ÿ”ข โฒ.
  • ๐Ÿ“จ โšซ๏ธ.
from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

โœ Pydantic ๐Ÿท

๐Ÿ—„ "๐Ÿ“„" ๐Ÿค™ "๐ŸŽป ๐ŸŽš", ๐Ÿ‘ฅ ๐Ÿ’ช ๐Ÿท ๐Ÿ‘ซ โฎ๏ธ Pydantic.

User ๐Ÿท

๐Ÿฅ‡, โžก๏ธ โœ User ๐Ÿท:

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

๐Ÿ‘ฅ ๐Ÿ”œ โš™๏ธ ๐Ÿ‘‰ ๐Ÿท ๐Ÿ‘† โžก ๐Ÿ› ๏ธ ๐Ÿ”ข,, ๐Ÿ‘ฅ ๐Ÿšซ ๐Ÿ”Œ โšซ๏ธ hashed_password.

UserInDB ๐Ÿท

๐Ÿ”œ, โžก๏ธ โœ UserInDB ๐Ÿท.

๐Ÿ‘‰ ๐Ÿ”œ โœ”๏ธ ๐Ÿ’ฝ ๐Ÿ‘ˆ ๐Ÿค™ ๐Ÿช ๐Ÿ’ฝ.

๐Ÿ‘ฅ ๐Ÿšซ โœ โšซ๏ธ ๐Ÿฟ Pydantic BaseModel โœ‹๏ธ ๐Ÿฟ ๐Ÿ‘† ๐Ÿ‘ User, โ†ฉ๏ธ โšซ๏ธ ๐Ÿ”œ โœ”๏ธ ๐ŸŒ ๐Ÿ”ข User โž• ๐Ÿ‘ฉโ€โคโ€๐Ÿ‘จ ๐ŸŒ…:

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

Note

๐Ÿ‘€ ๐Ÿ‘ˆ ๐Ÿ‘ฅ โœ”๏ธ hashed_password & type ๐Ÿ‘ ๐Ÿ‘ˆ ๐Ÿ”œ ๐Ÿช ๐Ÿ’ฝ.

โœ‹๏ธ โšซ๏ธ ๐Ÿšซ ๐Ÿ• ๐Ÿข User ๐Ÿท (1๏ธโƒฃ ๐Ÿ‘ฅ ๐Ÿ”œ ๐Ÿ“จ โžก ๐Ÿ› ๏ธ).

๐Ÿคš ๐Ÿ‘ฉโ€๐Ÿ’ป

๐Ÿ”œ โœ ๐Ÿ”ข ๐Ÿ‘ˆ ๐Ÿ”œ:

  • โœŠ ๐Ÿ†”.
  • ๐Ÿ— ๐Ÿ“„ ๐Ÿ†” โšช๏ธโžก๏ธ โšซ๏ธ.
  • ๐Ÿคš ๐Ÿ“„ โฎ๏ธ ๐Ÿ‘ˆ ๐Ÿ†”.
  • ๐Ÿšฎ ๐ŸŽš ๐Ÿ“„ UserInDB ๐Ÿท.

๐Ÿ— ๐Ÿ”ข ๐Ÿ‘ˆ ๐Ÿ•ด ๐Ÿ’ก ๐Ÿคš ๐Ÿ‘† ๐Ÿ‘ฉโ€๐Ÿ’ป โšช๏ธโžก๏ธ username (โš–๏ธ ๐Ÿ™† ๐ŸŽ ๐Ÿ”ข) ๐Ÿ”ฌ ๐Ÿ‘† โžก ๐Ÿ› ๏ธ ๐Ÿ”ข, ๐Ÿ‘† ๐Ÿ’ช ๐ŸŒ– ๐Ÿ’ช ๐Ÿค-โš™๏ธ โšซ๏ธ ๐Ÿ’— ๐Ÿ• & ๐Ÿšฎ โš’ ๐Ÿ’ฏ โšซ๏ธ:

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

โ“‚-๐ŸŽป

๐Ÿšฅ ๐Ÿ‘† ๐Ÿšซ ๐Ÿ˜ฐ โฎ๏ธ f"userprofile::{username}", โšซ๏ธ ๐Ÿ "โ“‚-๐ŸŽป".

๐Ÿ™† ๐Ÿ”ข ๐Ÿ‘ˆ ๐Ÿšฎ ๐Ÿ”˜ {} โ“‚-๐ŸŽป ๐Ÿ”œ โ†” / ๐Ÿ’‰ ๐ŸŽป.

dict ๐Ÿ—

๐Ÿšฅ ๐Ÿ‘† ๐Ÿšซ ๐Ÿ˜ฐ โฎ๏ธ UserInDB(**result.value), โšซ๏ธ โš™๏ธ dict "๐Ÿ—".

โšซ๏ธ ๐Ÿ”œ โœŠ dict result.value, & โœŠ ๐Ÿ”  ๐Ÿšฎ ๐Ÿ”‘ & ๐Ÿ’ฒ & ๐Ÿšถโ€โ™€๏ธ ๐Ÿ‘ซ ๐Ÿ”‘-๐Ÿ’ฒ UserInDB ๐Ÿ‡จ๐Ÿ‡ป โŒ.

, ๐Ÿšฅ dict ๐Ÿ”Œ:

{
    "username": "johndoe",
    "hashed_password": "some_hash",
}

โšซ๏ธ ๐Ÿ”œ ๐Ÿšถโ€โ™€๏ธ UserInDB :

UserInDB(username="johndoe", hashed_password="some_hash")

โœ ๐Ÿ‘† FastAPI ๐Ÿ“Ÿ

โœ FastAPI ๐Ÿ“ฑ

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

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

๐Ÿ‘† ๐Ÿ“Ÿ ๐Ÿค™ ๐Ÿ—„ & ๐Ÿ‘ฅ ๐Ÿšซ โš™๏ธ ๐Ÿฅผ ๐Ÿ await ๐Ÿ•โ€๐Ÿฆบ, ๐Ÿ‘ฅ ๐Ÿ”œ ๐Ÿ“ฃ ๐Ÿ‘† ๐Ÿ”ข โฎ๏ธ ๐Ÿ˜ def โ†ฉ๏ธ async def.

, ๐Ÿ—„ ๐Ÿ‘ ๐Ÿšซ โš™๏ธ ๐Ÿ‘ Bucket ๐ŸŽš ๐Ÿ’— "๐Ÿงตโ“‚",, ๐Ÿ‘ฅ ๐Ÿ’ช ๐Ÿคš ๐Ÿฅก ๐Ÿ”— & ๐Ÿšถโ€โ™€๏ธ โšซ๏ธ ๐Ÿ‘† ๐Ÿš™ ๐Ÿ”ข:

from typing import Union

from couchbase import LOCKMODE_WAIT
from couchbase.bucket import Bucket
from couchbase.cluster import Cluster, PasswordAuthenticator
from fastapi import FastAPI
from pydantic import BaseModel

USERPROFILE_DOC_TYPE = "userprofile"


def get_bucket():
    cluster = Cluster(
        "couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300"
    )
    authenticator = PasswordAuthenticator("username", "password")
    cluster.authenticate(authenticator)
    bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
    bucket.timeout = 30
    bucket.n1ql_timeout = 300
    return bucket


class User(BaseModel):
    username: str
    email: Union[str, None] = None
    full_name: Union[str, None] = None
    disabled: Union[bool, None] = None


class UserInDB(User):
    type: str = USERPROFILE_DOC_TYPE
    hashed_password: str


def get_user(bucket: Bucket, username: str):
    doc_id = f"userprofile::{username}"
    result = bucket.get(doc_id, quiet=True)
    if not result.value:
        return None
    user = UserInDB(**result.value)
    return user


# FastAPI specific code
app = FastAPI()


@app.get("/users/{username}", response_model=User)
def read_user(username: str):
    bucket = get_bucket()
    user = get_user(bucket=bucket, username=username)
    return user

๐ŸŒƒ

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ› ๏ธ ๐Ÿ™† ๐Ÿฅ‰ ๐Ÿฅณ โ˜ ๐Ÿ’ฝ, โš™๏ธ ๐Ÿ‘ซ ๐Ÿฉ ๐Ÿ“ฆ.

๐ŸŽ โœ” ๐Ÿ™† ๐ŸŽ ๐Ÿ”ข ๐Ÿงฐ, โš™๏ธ โš–๏ธ ๐Ÿ› ๏ธ.