-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Pydantic BaseSettings for config settings #87
Conversation
88f4e33
to
a59f546
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love it 🥇
I didnot realize that pydantic provided the BaseSettings
class. It's great 🎈
a59f546
to
194132c
Compare
@@ -41,7 +41,7 @@ def update( | |||
self, db_session: Session, *, db_obj: ModelType, obj_in: UpdateSchemaType | |||
) -> ModelType: | |||
obj_data = jsonable_encoder(db_obj) | |||
update_data = obj_in.dict(skip_defaults=True) | |||
update_data = obj_in.dict(exclude_unset=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will conflict with PR #106
This reflects the improved implementation in fastapi/full-stack-fastapi-template#87
This reflects the improved implementation in fastapi/full-stack-fastapi-template#87
This reflects the improved implementation in fastapi/full-stack-fastapi-template#87
This reflects the improved implementation in fastapi/full-stack-fastapi-template#87
@StephenBrown2 just wondering if using Pydantic is superior to using Starlette config ? https://www.starlette.io/config/ Especially considering security usecases where we do not commit ".env" into the source code repo. Starlette config supports all those kind of cases. Pretty sure you can write them... so just curious |
Pydantic by default reads form the environment, but can also read from a dotenv file, as long as the python-dotenv package is installed as well: https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support
I see them as equivalent, and prefer Pydantic's method, but if one is not using Pydantic and instead using Starlette alone, it's perfectly fine to use that. |
Thanks for your reply. The only reason I asked was that fastapi is built on
Starlette and that uses this config system. So i was concerned that was the
long term safer way
…On Tue, 25 Feb, 2020, 21:15 Stephen Brown II, ***@***.***> wrote:
Pydantic by default reads form the environment, but can also read from a
dotenv file, as long as the python-dotenv
<https://pypi.org/project/python-dotenv/> package
<https://pypi.org/project/python-dotenv/> is installed as well:
https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support
Since Pydantic is already being used for validation/parsing, it seemed
logical to use it for settings as well. One difference is that settings
must be in a class, but that can come in useful for setting config in
multiple ways, giving it one more option than Starlette's Config:
Setting value is determined as follows (in descending order of priority):
1. Arguments passed to the Settings class initialiser.
2. Environment variables, e.g. my_prefix_special_function as described
above.
3. Variables loaded from a dotenv (.env) file.
4. The default field values for the Settings model.
I see them as equivalent, and prefer Pydantic's method, but if one is not
using Pydantic and instead using Starlette alone, it's perfectly fine to
use that.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#87>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAASYU5QJ6YWC5SBMEFKGUTREU4JJANCNFSM4JXFGMDA>
.
|
Aye, but FastAPI is also built on Pydantic for the data parts, so either option should work fine for the long term. One benefit Starlette's implementation might have is it understands Comma Separated Strings, while Pydantic requires complex vars to be in JSON, so if we used that, we wouldn't need to change BACKEND_CORS_ORIGINS https://github.com/tiangolo/full-stack-fastapi-postgresql/pull/87/files#diff-d7ae4ef57958180c199332f0ce9c5a2fR13 |
Personally I like Pydantic's You can also use sub models to structure settings somewhat. Prefixes can be set via the Example: from pathlib import Path
from typing import List
from pydantic import (
AnyHttpUrl,
BaseModel,
BaseSettings,
FilePath,
PostgresDsn,
SecretStr,
)
class Paths(BaseModel):
"""File paths class. Build file paths using APP_DIR."""
APP_DIR: FilePath = Path(__file__).resolve().parent
STATIC_DIR: FilePath = APP_DIR.joinpath("static")
# Docker secrets directory
SECRETS_DIR: FilePath = "/run/secrets"
class PostgresSettings(BaseSettings):
USER: str
PASSWORD: SecretStr
HOST: str
PORT: int
DB: str
class Config:
env_prefix = "POSTGRES_"
class SMTPSettings(BaseSettings):
USER: str
PASSWORD: SecretStr
TLS: bool
SSL: bool
HOST: str
PORT: int
class Config:
env_prefix = "SMTP_"
class JWTSettings(BaseSettings):
EXPIRE_MINUTES: int = 60 * 24 * 8 # 60 minutes * 24 hours * 8 days = 8 days
EMAIL_EXPIRE_MINUTES: int = 60 * 8 # 8 hours
class Config:
env_prefix = "JWT_"
class Settings(BaseSettings):
PATHS = Paths()
POSTGRES = PostgresSettings()
BASE_DB_URL: PostgresDsn = f"postgresql://{POSTGRES.USER}:{POSTGRES.PASSWORD.get_secret_value()}@{POSTGRES.HOST}:{POSTGRES.PORT}"
DATABASE_URL: PostgresDsn = BASE_DB_URL + f"/{POSTGRES.DB}"
TEST_DATABASE_URL: PostgresDsn = BASE_DB_URL + f"/{POSTGRES.DB}_test"
SMTP: SMTPSettings = SMTPSettings()
JWT: JWTSettings = JWTSettings()
PROJECT_NAME: str
SERVER_HOST: AnyHttpUrl = "http://0.0.0.0"
CORS_WHITELIST: List[AnyHttpUrl] = []
FASTAPI_ENV: str
TESTING: bool = False
DEBUG: bool = False
FIRST_SUPERUSER: str
FIRST_SUPERUSER_PASSWORD: str
USERS_OPEN_REGISTRATION: bool
settings = Settings() |
Great job @StephenBrown2 ! 🙇 🤓 Thanks for your contribution! 🚀 🎉 |
* Use Pydantic BaseSettings for config settings * Update fastapi dep to >=0.47.0 and email_validator to email-validator * Fix deprecation warning for Pydantic >=1.0 * Properly support old-format comma separated strings for BACKEND_CORS_ORIGINS Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Enables the use of validation for config on load, and pulling from environment implicitly.
I believe I got all the types right, mostly strings. All of the values not critical for running (i.e. email settings) also have a default value, and so are optional. Others, those populated by cookiecutter, are required.
I also updated some deps to be consistent throughout and changed a single keyword arg to match Pydantic 1.0 usage, but I can back those out if needed.