├── .gitignore
├── LICENSE
├── README.md
├── chapter01
└── asyncio
│ ├── contrast_async_other.py
│ ├── contrast_sync.py
│ └── cotrast_async.py
├── chapter02
├── main.py
├── static
│ └── css
│ │ └── style.css
└── templates
│ ├── index.html
│ └── yyy.txt
├── chapter03
├── async_sync
│ └── main.py
├── background_tasks
│ └── main.py
├── close_docs
│ └── main.py
├── configparser_config
│ ├── conf.ini
│ └── main.py
├── debugshow
│ └── main.py
├── env_config
│ ├── .env
│ └── main.py
├── global_exception
│ └── main.py
├── localswagger
│ ├── main.py
│ └── static
│ │ ├── swagger-ui-bundle.js
│ │ └── swagger-ui.css
├── more_routers
│ └── main.py
├── mount_app
│ ├── fastapiapp.py
│ └── flaskapp.py
├── parameter_body
│ └── main.py
├── parameter_cookie
│ └── main.py
├── parameter_form_and_file
│ ├── data.bat
│ └── main.py
├── parameter_header
│ └── main.py
├── parameter_path
│ └── main.py
├── parameter_query
│ └── main.py
├── parameter_request
│ └── main.py
├── parameter_response
│ ├── data.bat
│ ├── main_file_response.py
│ ├── main_html_response.py
│ ├── main_json_response.py
│ ├── main_plain_text_response.py
│ ├── main_redirect_response.py
│ ├── main_response_model.py
│ ├── main_status_code.py
│ ├── main_streaming_response.py
│ └── main_xml_response.py
├── startup_shutdown
│ └── main.py
├── static_dynamic
│ └── main.py
└── swaggershow
│ └── main.py
├── chapter04
├── business_error
│ └── main.py
├── custom_exception
│ └── main.py
├── http_exception
│ └── main.py
├── middleware_exception
│ └── main.py
└── request_validation_error
│ └── main.py
├── chapter05
├── body
│ └── main.py
├── pydantic_base
│ └── main.py
├── pydantic_fastapi_get
│ └── main.py
├── pydantic_fastapi_post
│ └── main.py
├── pydantic_field
│ └── main.py
├── pydantic_obj_to_dict_json
│ └── main.py
├── pydantic_orm
│ └── main.py
├── pydantic_validator
│ ├── address_error_main.py
│ ├── main.py
│ ├── root_validator_main.py
│ └── share_logic_auth_main.py
└── pydantic_validator_order
│ └── main.py
├── chapter06
├── depend_class
│ └── main.py
├── depend_class_more_depends
│ └── main.py
├── depend_class_nest_depends
│ └── main.py
├── depend_func
│ └── main.py
├── depend_global_depends
│ └── main.py
└── depend_group_router
│ └── main.py
├── chapter07
├── base_http_middleware
│ └── main.py
├── cors_middleware
│ └── main.py
├── https_redirect_middleware
│ └── main.py
├── log_response_middleware
│ └── main.py
├── middleware_process_time
│ └── main.py
├── tracdid_middleware
│ └── main.py
├── trusted_host_middleware
│ └── main.py
└── whileIp_middleware
│ └── main.py
├── chapter08
├── aioredis_fastapi
│ └── main.py
├── aioredis_lock
│ └── main.py
├── aioredis_pubsub
│ └── main.py
├── databases_sql
│ ├── main.py
│ └── user.db
├── databases_sqlalchemy
│ ├── main.py
│ └── user.db
├── fastapi_sqlalchemy
│ ├── alembic.ini
│ ├── alembic
│ │ ├── README
│ │ ├── env.py
│ │ ├── script.py.mako
│ │ └── versions
│ │ │ ├── 287a3cf31b84_shann.py
│ │ │ └── 3328ff109aa7_add_mobile.py
│ ├── api
│ │ ├── __init__.py
│ │ └── user.py
│ ├── config
│ │ ├── __init__.py
│ │ └── confiig.py
│ ├── db
│ │ ├── __init__.py
│ │ └── database.py
│ ├── dependencies
│ │ └── __init__.py
│ ├── main.py
│ ├── models
│ │ ├── __init__.py
│ │ └── user.py
│ ├── schemas
│ │ ├── __init__.py
│ │ └── user.py
│ ├── servies
│ │ ├── __init__.py
│ │ └── user.py
│ └── user.db
├── lua_register_script
│ ├── 2mian.py
│ └── mian.py
├── sql_model
│ └── main.py
├── sqlalchemy_async_sqlite3
│ ├── aiosqlite_user.db
│ └── main.py
├── sqlalchemy_sync_sqlite3
│ ├── main.py
│ └── user.db
├── sqlite3_connect
│ ├── main.py
│ └── test.db
├── sqlmodel_async_sqlite3
│ ├── aiosqlite_user.db
│ └── main.py
└── sqlmodel_sync_sqlite3
│ ├── main.py
│ └── user.db
├── chapter09
├── api_key
│ └── main.py
├── http_basic
│ └── main.py
├── http_digest
│ └── main.py
├── jwt_use
│ └── main.py
├── mode_client
│ └── main.py
├── mode_code
│ ├── get_token.py
│ └── main.py
└── mode_password
│ └── main.py
├── chapter10
├── shorr_url_pro
│ ├── api
│ │ ├── __init__.py
│ │ ├── short.py
│ │ └── user.py
│ ├── config
│ │ ├── __init__.py
│ │ └── config.py
│ ├── db
│ │ ├── __init__.py
│ │ └── database.py
│ ├── dependencies
│ │ └── __init__.py
│ ├── main.py
│ ├── models
│ │ ├── __init__.py
│ │ └── model.py
│ ├── schemas
│ │ ├── __init__.py
│ │ └── user.py
│ ├── servies
│ │ ├── __init__.py
│ │ ├── short.py
│ │ └── user.py
│ ├── short.db
│ └── utils
│ │ └── __init__.py
├── short_url_pro
│ ├── api
│ │ ├── __init__.py
│ │ ├── short.py
│ │ └── user.py
│ ├── app.py
│ ├── config
│ │ ├── __init__.py
│ │ └── config.py
│ ├── db
│ │ ├── __init__.py
│ │ └── database.py
│ ├── dependencies
│ │ └── __init__.py
│ ├── main.py
│ ├── models
│ │ ├── __init__.py
│ │ └── model.py
│ ├── schemas
│ │ └── __init__.py
│ ├── servies
│ │ ├── __init__.py
│ │ ├── short.db
│ │ ├── short.py
│ │ └── user.py
│ ├── short.db
│ └── utils
│ │ ├── __init__.py
│ │ ├── auth_helper.py
│ │ ├── passlib_hepler.py
│ │ └── random_helper.py
└── 测试生成模型.pdma.json
├── chapter11
├── distributed_websocket
│ ├── api
│ │ ├── __init__.py
│ │ ├── room.py
│ │ └── user.py
│ ├── app.py
│ ├── chat.db
│ ├── config
│ │ ├── __init__.py
│ │ └── config.py
│ ├── db
│ │ ├── __init__.py
│ │ └── database.py
│ ├── dependencies
│ │ └── __init__.py
│ ├── main.py
│ ├── models
│ │ ├── __init__.py
│ │ └── model.py
│ ├── schemas
│ │ └── __init__.py
│ ├── servies
│ │ ├── __init__.py
│ │ └── user.py
│ ├── templates
│ │ ├── login.html
│ │ ├── register.html
│ │ └── room.html
│ └── utils
│ │ ├── __init__.py
│ │ ├── auth_helper.py
│ │ ├── passlib_hepler.py
│ │ ├── random_helper.py
│ │ ├── room_connection_helper.py
│ │ └── room_connection_helper_distributed.py
└── websocket
│ ├── api
│ ├── __init__.py
│ ├── room.py
│ └── user.py
│ ├── app.py
│ ├── chat.db
│ ├── config
│ ├── __init__.py
│ └── config.py
│ ├── db
│ ├── __init__.py
│ └── database.py
│ ├── dependencies
│ └── __init__.py
│ ├── main.py
│ ├── models
│ ├── __init__.py
│ └── model.py
│ ├── schemas
│ └── __init__.py
│ ├── servies
│ ├── __init__.py
│ └── user.py
│ ├── templates
│ ├── login.html
│ ├── register.html
│ └── room.html
│ └── utils
│ ├── __init__.py
│ ├── auth_helper.py
│ ├── passlib_hepler.py
│ ├── random_helper.py
│ └── room_connection_helper.py
├── chapter12
└── booking_system
│ ├── __init__.py
│ ├── apis
│ ├── __init__.py
│ ├── doctor
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ └── doctor_api.py
│ │ ├── dependencies
│ │ │ └── __init__.py
│ │ ├── repository
│ │ │ └── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── hospital
│ │ ├── __init__.py
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ └── get_hospital_info.py
│ │ └── repository
│ │ │ └── __init__.py
│ ├── payorders
│ │ ├── __init__.py
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ ├── doctor_order_check.py
│ │ │ ├── doctor_reserve_order.py
│ │ │ ├── doctor_reserve_reorder.py
│ │ │ ├── payback_reserve_order.py
│ │ │ └── reserve_order_info.py
│ │ ├── dependencies
│ │ │ └── __init__.py
│ │ ├── repository
│ │ │ └── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ └── userorders
│ │ ├── __init__.py
│ │ ├── api
│ │ ├── __init__.py
│ │ ├── refund_reserve_order.py
│ │ ├── unpay_reserve_order.py
│ │ ├── user_order_info.py
│ │ ├── user_order_list.py
│ │ └── wxauth_login.py
│ │ ├── repository
│ │ └── __init__.py
│ │ └── schemas
│ │ └── __init__.py
│ ├── app.py
│ ├── app_sync.py
│ ├── config
│ ├── __init__.py
│ └── config.py
│ ├── db
│ ├── __init__.py
│ ├── async_database.py
│ ├── models.py
│ └── sync_database.py
│ ├── exts
│ ├── __init__.py
│ ├── async_rabbit
│ │ └── __init__.py
│ ├── exceptions
│ │ └── __init__.py
│ ├── logururoute
│ │ ├── __init__.py
│ │ └── config.py
│ ├── rabbit
│ │ └── __init__.py
│ ├── rabbit2
│ │ └── __init__.py
│ ├── requestvar
│ │ ├── __init__.py
│ │ └── bing.py
│ ├── responses
│ │ ├── __init__.py
│ │ └── json_response.py
│ └── wechatpy
│ │ ├── __init__.py
│ │ ├── _compat.py
│ │ ├── client
│ │ ├── __init__.py
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── card.py
│ │ │ ├── customservice.py
│ │ │ ├── datacube.py
│ │ │ ├── device.py
│ │ │ ├── group.py
│ │ │ ├── invoice.py
│ │ │ ├── jsapi.py
│ │ │ ├── marketing.py
│ │ │ ├── material.py
│ │ │ ├── media.py
│ │ │ ├── menu.py
│ │ │ ├── merchant
│ │ │ │ ├── __init__.py
│ │ │ │ ├── category.py
│ │ │ │ ├── common.py
│ │ │ │ ├── express.py
│ │ │ │ ├── group.py
│ │ │ │ ├── order.py
│ │ │ │ ├── shelf.py
│ │ │ │ └── stock.py
│ │ │ ├── message.py
│ │ │ ├── misc.py
│ │ │ ├── poi.py
│ │ │ ├── qrcode.py
│ │ │ ├── scan.py
│ │ │ ├── semantic.py
│ │ │ ├── shakearound.py
│ │ │ ├── tag.py
│ │ │ ├── template.py
│ │ │ ├── user.py
│ │ │ ├── wifi.py
│ │ │ └── wxa.py
│ │ └── base.py
│ │ ├── component.py
│ │ ├── constants.py
│ │ ├── crypto
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── cryptography.py
│ │ ├── pkcs7.py
│ │ └── pycrypto.py
│ │ ├── enterprise
│ │ ├── __init__.py
│ │ ├── client
│ │ │ ├── __init__.py
│ │ │ └── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── agent.py
│ │ │ │ ├── appchat.py
│ │ │ │ ├── batch.py
│ │ │ │ ├── chat.py
│ │ │ │ ├── department.py
│ │ │ │ ├── jsapi.py
│ │ │ │ ├── material.py
│ │ │ │ ├── media.py
│ │ │ │ ├── menu.py
│ │ │ │ ├── message.py
│ │ │ │ ├── misc.py
│ │ │ │ ├── oauth.py
│ │ │ │ ├── service.py
│ │ │ │ ├── shakearound.py
│ │ │ │ ├── tag.py
│ │ │ │ └── user.py
│ │ ├── crypto.py
│ │ ├── events.py
│ │ ├── exceptions.py
│ │ ├── messages.py
│ │ ├── parser.py
│ │ └── replies.py
│ │ ├── events.py
│ │ ├── exceptions.py
│ │ ├── fields.py
│ │ ├── messages.py
│ │ ├── oauth.py
│ │ ├── parser.py
│ │ ├── pay
│ │ ├── __init__.py
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ ├── coupon.py
│ │ │ ├── jsapi.py
│ │ │ ├── micropay.py
│ │ │ ├── order.py
│ │ │ ├── redpack.py
│ │ │ ├── refund.py
│ │ │ ├── tools.py
│ │ │ ├── transfer.py
│ │ │ └── withhold.py
│ │ ├── base.py
│ │ └── utils.py
│ │ ├── replies.py
│ │ ├── session
│ │ ├── __init__.py
│ │ ├── memcachedstorage.py
│ │ ├── memorystorage.py
│ │ ├── redisstorage.py
│ │ └── shovestorage.py
│ │ └── utils.py
│ ├── main.py
│ ├── middlewares
│ ├── __init__.py
│ └── loger
│ │ ├── __init__.py
│ │ ├── bing.py
│ │ └── middleware.py
│ ├── order_consumer.py
│ ├── plugins
│ ├── __init__.py
│ ├── base.py
│ └── request_hook.py
│ ├── requirements.txt
│ ├── static
│ ├── swagger-ui-bundle.js
│ └── swagger-ui.css
│ ├── utils
│ ├── __init__.py
│ ├── cast_helper.py
│ ├── datatime_helper.py
│ ├── json_helper.py
│ ├── ordernum_helper.py
│ ├── run_with_asyncio.py
│ └── xmlhelper.py
│ └── wxchatsdk
│ └── __init__.py
├── chapter13
├── booking_system
│ ├── __init__.py
│ ├── apis
│ │ ├── __init__.py
│ │ ├── doctor
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ └── doctor_api.py
│ │ │ ├── dependencies
│ │ │ │ └── __init__.py
│ │ │ ├── repository
│ │ │ │ └── __init__.py
│ │ │ └── schemas
│ │ │ │ └── __init__.py
│ │ ├── hospital
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ └── get_hospital_info.py
│ │ │ └── repository
│ │ │ │ └── __init__.py
│ │ ├── payorders
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── doctor_order_check.py
│ │ │ │ ├── doctor_reserve_order.py
│ │ │ │ ├── doctor_reserve_reorder.py
│ │ │ │ ├── payback_reserve_order.py
│ │ │ │ └── reserve_order_info.py
│ │ │ ├── dependencies
│ │ │ │ └── __init__.py
│ │ │ ├── repository
│ │ │ │ └── __init__.py
│ │ │ └── schemas
│ │ │ │ └── __init__.py
│ │ └── userorders
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ ├── __init__.py
│ │ │ ├── refund_reserve_order.py
│ │ │ ├── unpay_reserve_order.py
│ │ │ ├── user_order_info.py
│ │ │ ├── user_order_list.py
│ │ │ └── wxauth_login.py
│ │ │ ├── repository
│ │ │ └── __init__.py
│ │ │ └── schemas
│ │ │ └── __init__.py
│ ├── app.py
│ ├── app_sync.py
│ ├── config
│ │ ├── __init__.py
│ │ └── config.py
│ ├── db
│ │ ├── __init__.py
│ │ ├── async_database.py
│ │ ├── models.py
│ │ └── sync_database.py
│ ├── exts
│ │ ├── __init__.py
│ │ ├── async_rabbit
│ │ │ └── __init__.py
│ │ ├── exceptions
│ │ │ └── __init__.py
│ │ ├── logururoute
│ │ │ ├── __init__.py
│ │ │ └── config.py
│ │ ├── rabbit
│ │ │ └── __init__.py
│ │ ├── rabbit2
│ │ │ └── __init__.py
│ │ ├── requestvar
│ │ │ ├── __init__.py
│ │ │ └── bing.py
│ │ ├── responses
│ │ │ ├── __init__.py
│ │ │ └── json_response.py
│ │ └── wechatpy
│ │ │ ├── __init__.py
│ │ │ ├── _compat.py
│ │ │ ├── client
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── base.py
│ │ │ │ ├── card.py
│ │ │ │ ├── customservice.py
│ │ │ │ ├── datacube.py
│ │ │ │ ├── device.py
│ │ │ │ ├── group.py
│ │ │ │ ├── invoice.py
│ │ │ │ ├── jsapi.py
│ │ │ │ ├── marketing.py
│ │ │ │ ├── material.py
│ │ │ │ ├── media.py
│ │ │ │ ├── menu.py
│ │ │ │ ├── merchant
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── category.py
│ │ │ │ │ ├── common.py
│ │ │ │ │ ├── express.py
│ │ │ │ │ ├── group.py
│ │ │ │ │ ├── order.py
│ │ │ │ │ ├── shelf.py
│ │ │ │ │ └── stock.py
│ │ │ │ ├── message.py
│ │ │ │ ├── misc.py
│ │ │ │ ├── poi.py
│ │ │ │ ├── qrcode.py
│ │ │ │ ├── scan.py
│ │ │ │ ├── semantic.py
│ │ │ │ ├── shakearound.py
│ │ │ │ ├── tag.py
│ │ │ │ ├── template.py
│ │ │ │ ├── user.py
│ │ │ │ ├── wifi.py
│ │ │ │ └── wxa.py
│ │ │ └── base.py
│ │ │ ├── component.py
│ │ │ ├── constants.py
│ │ │ ├── crypto
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── cryptography.py
│ │ │ ├── pkcs7.py
│ │ │ └── pycrypto.py
│ │ │ ├── enterprise
│ │ │ ├── __init__.py
│ │ │ ├── client
│ │ │ │ ├── __init__.py
│ │ │ │ └── api
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── agent.py
│ │ │ │ │ ├── appchat.py
│ │ │ │ │ ├── batch.py
│ │ │ │ │ ├── chat.py
│ │ │ │ │ ├── department.py
│ │ │ │ │ ├── jsapi.py
│ │ │ │ │ ├── material.py
│ │ │ │ │ ├── media.py
│ │ │ │ │ ├── menu.py
│ │ │ │ │ ├── message.py
│ │ │ │ │ ├── misc.py
│ │ │ │ │ ├── oauth.py
│ │ │ │ │ ├── service.py
│ │ │ │ │ ├── shakearound.py
│ │ │ │ │ ├── tag.py
│ │ │ │ │ └── user.py
│ │ │ ├── crypto.py
│ │ │ ├── events.py
│ │ │ ├── exceptions.py
│ │ │ ├── messages.py
│ │ │ ├── parser.py
│ │ │ └── replies.py
│ │ │ ├── events.py
│ │ │ ├── exceptions.py
│ │ │ ├── fields.py
│ │ │ ├── messages.py
│ │ │ ├── oauth.py
│ │ │ ├── parser.py
│ │ │ ├── pay
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── coupon.py
│ │ │ │ ├── jsapi.py
│ │ │ │ ├── micropay.py
│ │ │ │ ├── order.py
│ │ │ │ ├── redpack.py
│ │ │ │ ├── refund.py
│ │ │ │ ├── tools.py
│ │ │ │ ├── transfer.py
│ │ │ │ └── withhold.py
│ │ │ ├── base.py
│ │ │ └── utils.py
│ │ │ ├── replies.py
│ │ │ ├── session
│ │ │ ├── __init__.py
│ │ │ ├── memcachedstorage.py
│ │ │ ├── memorystorage.py
│ │ │ ├── redisstorage.py
│ │ │ └── shovestorage.py
│ │ │ └── utils.py
│ ├── main.py
│ ├── middlewares
│ │ ├── __init__.py
│ │ └── loger
│ │ │ ├── __init__.py
│ │ │ ├── bing.py
│ │ │ └── middleware.py
│ ├── order_consumer.py
│ ├── plugins
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── request_hook.py
│ ├── requirements.txt
│ ├── static
│ │ ├── swagger-ui-bundle.js
│ │ └── swagger-ui.css
│ ├── testcase
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_async_api_v1.py
│ │ ├── test_async_api_v2.py
│ │ └── test_sync_api.py
│ ├── utils
│ │ ├── __init__.py
│ │ ├── cast_helper.py
│ │ ├── datatime_helper.py
│ │ ├── json_helper.py
│ │ ├── ordernum_helper.py
│ │ ├── run_with_asyncio.py
│ │ └── xmlhelper.py
│ └── wxchatsdk
│ │ └── __init__.py
├── pytest_demo
│ ├── cast_helper.py
│ └── test_add.py
├── pytest_fixture_demo
│ ├── testcase
│ │ ├── conftest.py
│ │ └── test_case1.py
│ └── tests
│ │ ├── __init__.py
│ │ ├── test_fixs.py
│ │ ├── test_fixs_parametrize.py
│ │ ├── test_fixs_parametrize_class.py
│ │ └── test_fixs_params.py
└── unittest_demo
│ └── main.py
├── chapter14
├── app.ini
├── booking_system
│ ├── .drone.yml
│ ├── Dockerfile
│ ├── __init__.py
│ ├── apis
│ │ ├── __init__.py
│ │ ├── doctor
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ └── doctor_api.py
│ │ │ ├── dependencies
│ │ │ │ └── __init__.py
│ │ │ ├── repository
│ │ │ │ └── __init__.py
│ │ │ └── schemas
│ │ │ │ └── __init__.py
│ │ ├── hospital
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ └── get_hospital_info.py
│ │ │ └── repository
│ │ │ │ └── __init__.py
│ │ ├── payorders
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── doctor_order_check.py
│ │ │ │ ├── doctor_reserve_order.py
│ │ │ │ ├── doctor_reserve_reorder.py
│ │ │ │ ├── payback_reserve_order.py
│ │ │ │ └── reserve_order_info.py
│ │ │ ├── dependencies
│ │ │ │ └── __init__.py
│ │ │ ├── repository
│ │ │ │ └── __init__.py
│ │ │ └── schemas
│ │ │ │ └── __init__.py
│ │ └── userorders
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ ├── __init__.py
│ │ │ ├── refund_reserve_order.py
│ │ │ ├── unpay_reserve_order.py
│ │ │ ├── user_order_info.py
│ │ │ ├── user_order_list.py
│ │ │ └── wxauth_login.py
│ │ │ ├── repository
│ │ │ └── __init__.py
│ │ │ └── schemas
│ │ │ └── __init__.py
│ ├── app.py
│ ├── app_sync.py
│ ├── config
│ │ ├── __init__.py
│ │ └── config.py
│ ├── db
│ │ ├── __init__.py
│ │ ├── async_database.py
│ │ ├── models.py
│ │ └── sync_database.py
│ ├── docker-compose.yml
│ ├── exts
│ │ ├── __init__.py
│ │ ├── async_rabbit
│ │ │ └── __init__.py
│ │ ├── exceptions
│ │ │ └── __init__.py
│ │ ├── logururoute
│ │ │ ├── __init__.py
│ │ │ └── config.py
│ │ ├── rabbit
│ │ │ └── __init__.py
│ │ ├── rabbit2
│ │ │ └── __init__.py
│ │ ├── requestvar
│ │ │ ├── __init__.py
│ │ │ └── bing.py
│ │ ├── responses
│ │ │ ├── __init__.py
│ │ │ └── json_response.py
│ │ └── wechatpy
│ │ │ ├── __init__.py
│ │ │ ├── _compat.py
│ │ │ ├── client
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── base.py
│ │ │ │ ├── card.py
│ │ │ │ ├── customservice.py
│ │ │ │ ├── datacube.py
│ │ │ │ ├── device.py
│ │ │ │ ├── group.py
│ │ │ │ ├── invoice.py
│ │ │ │ ├── jsapi.py
│ │ │ │ ├── marketing.py
│ │ │ │ ├── material.py
│ │ │ │ ├── media.py
│ │ │ │ ├── menu.py
│ │ │ │ ├── merchant
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── category.py
│ │ │ │ │ ├── common.py
│ │ │ │ │ ├── express.py
│ │ │ │ │ ├── group.py
│ │ │ │ │ ├── order.py
│ │ │ │ │ ├── shelf.py
│ │ │ │ │ └── stock.py
│ │ │ │ ├── message.py
│ │ │ │ ├── misc.py
│ │ │ │ ├── poi.py
│ │ │ │ ├── qrcode.py
│ │ │ │ ├── scan.py
│ │ │ │ ├── semantic.py
│ │ │ │ ├── shakearound.py
│ │ │ │ ├── tag.py
│ │ │ │ ├── template.py
│ │ │ │ ├── user.py
│ │ │ │ ├── wifi.py
│ │ │ │ └── wxa.py
│ │ │ └── base.py
│ │ │ ├── component.py
│ │ │ ├── constants.py
│ │ │ ├── crypto
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── cryptography.py
│ │ │ ├── pkcs7.py
│ │ │ └── pycrypto.py
│ │ │ ├── enterprise
│ │ │ ├── __init__.py
│ │ │ ├── client
│ │ │ │ ├── __init__.py
│ │ │ │ └── api
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── agent.py
│ │ │ │ │ ├── appchat.py
│ │ │ │ │ ├── batch.py
│ │ │ │ │ ├── chat.py
│ │ │ │ │ ├── department.py
│ │ │ │ │ ├── jsapi.py
│ │ │ │ │ ├── material.py
│ │ │ │ │ ├── media.py
│ │ │ │ │ ├── menu.py
│ │ │ │ │ ├── message.py
│ │ │ │ │ ├── misc.py
│ │ │ │ │ ├── oauth.py
│ │ │ │ │ ├── service.py
│ │ │ │ │ ├── shakearound.py
│ │ │ │ │ ├── tag.py
│ │ │ │ │ └── user.py
│ │ │ ├── crypto.py
│ │ │ ├── events.py
│ │ │ ├── exceptions.py
│ │ │ ├── messages.py
│ │ │ ├── parser.py
│ │ │ └── replies.py
│ │ │ ├── events.py
│ │ │ ├── exceptions.py
│ │ │ ├── fields.py
│ │ │ ├── messages.py
│ │ │ ├── oauth.py
│ │ │ ├── parser.py
│ │ │ ├── pay
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── coupon.py
│ │ │ │ ├── jsapi.py
│ │ │ │ ├── micropay.py
│ │ │ │ ├── order.py
│ │ │ │ ├── redpack.py
│ │ │ │ ├── refund.py
│ │ │ │ ├── tools.py
│ │ │ │ ├── transfer.py
│ │ │ │ └── withhold.py
│ │ │ ├── base.py
│ │ │ └── utils.py
│ │ │ ├── replies.py
│ │ │ ├── session
│ │ │ ├── __init__.py
│ │ │ ├── memcachedstorage.py
│ │ │ ├── memorystorage.py
│ │ │ ├── redisstorage.py
│ │ │ └── shovestorage.py
│ │ │ └── utils.py
│ ├── main.py
│ ├── middlewares
│ │ ├── __init__.py
│ │ └── loger
│ │ │ ├── __init__.py
│ │ │ ├── bing.py
│ │ │ └── middleware.py
│ ├── order_consumer.py
│ ├── plugins
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── request_hook.py
│ ├── requirements.txt
│ ├── static
│ │ ├── swagger-ui-bundle.js
│ │ └── swagger-ui.css
│ ├── testcase
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_async_api_v1.py
│ │ ├── test_async_api_v2.py
│ │ └── test_sync_api.py
│ ├── utils
│ │ ├── __init__.py
│ │ ├── cast_helper.py
│ │ ├── datatime_helper.py
│ │ ├── json_helper.py
│ │ ├── ordernum_helper.py
│ │ ├── run_with_asyncio.py
│ │ └── xmlhelper.py
│ └── wxchatsdk
│ │ └── __init__.py
└── drone_docker-compose.yml
├── chapter15
├── Fastapi_cProfile
│ ├── .prof
│ └── main.py
├── Jaeger
│ ├── test_jaeger_client
│ │ └── main.py
│ └── test_jaeger_client_fastapi
│ │ └── middeware
│ │ ├── __init__.py
│ │ └── main.py
├── async_sync_change
│ ├── main_asgiref_async_to_sync.py
│ ├── main_asgiref_sync_to_async.py
│ ├── main_asyncer_asyncify.py
│ └── main_asyncer_syncify.py
├── async_wrapper
│ ├── .runtest.prof
│ └── main_asgiref_sync_to_async.py
├── body
│ ├── main_01.py
│ ├── main_02.py
│ ├── main_03.py
│ └── main_04.py
├── cProfile
│ ├── c_profile_text_run.py
│ ├── crpresutl.svg
│ ├── runtest.prof
│ ├── runtest_profile.stats
│ └── runtest_profile_stats_run.py
├── contextvar_request
│ ├── bind_.py
│ ├── main_class.py
│ └── request.py
├── depends
│ ├── main_class.py
│ ├── main_class_call.py
│ ├── main_class_security_scopes.py
│ ├── main_fun.py
│ └── main_fun_security_scopes.py
├── fastapi_cache
│ ├── main.py
│ └── uu.py
├── model_sort
│ └── main_asyncer_syncify.py
├── plugins
│ ├── base.py
│ └── main.py
├── sentry
│ ├── __init__.py
│ └── main.py
└── smtplib
│ ├── main_aiosmtplib.py
│ ├── main_smtplib.py
│ ├── test.jpg
│ ├── test1.txt
│ └── test2.txt
└── chapter16
├── Jaeger
├── test_jaeger_client
│ └── main.py
└── test_jaeger_client_fastapi
│ └── middeware
│ ├── __init__.py
│ └── main.py
├── async_sync_change
├── main_asgiref_async_to_sync.py
├── main_asgiref_sync_to_async.py
├── main_asyncer_asyncify.py
└── main_asyncer_syncify.py
├── async_wrapper
├── .runtest.prof
└── main_asgiref_sync_to_async.py
├── body
├── main_01.py
├── main_02.py
├── main_03.py
└── main_04.py
├── contextvar_request
├── bind_.py
├── main_class.py
└── request.py
├── depends
├── main_class.py
├── main_class_call.py
├── main_class_security_scopes.py
├── main_fun.py
└── main_fun_security_scopes.py
├── model_sort
└── main_asyncer_syncify.py
├── plugins
├── base.py
└── main.py
├── sentry
├── __init__.py
└── main.py
└── smtplib
├── aaaa.py
├── main_aiosmtplib.py
├── main_smtplib.py
├── test.jpg
├── test1.txt
└── test2.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .diea/
3 | .DS_Store
4 | __pycache__/
5 | *.py[cod]
6 |
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 zyx
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter01/asyncio/contrast_sync.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import time
3 |
4 | def take_up_time(func):
5 | def wrapper(*args, **kwargs):
6 | print("开始执行---->")
7 | now = time.time()
8 | result = func(*args, **kwargs)
9 | using = (time.time() - now) * 1000
10 | print(f"结束执行,消耗时间为:{using}ms")
11 | return result
12 | return wrapper
13 |
14 | def request_sync(url):
15 | response = requests.get(url)
16 | return response
17 |
18 | @take_up_time
19 | def run():
20 | for i in range(0, 50):
21 | request_sync('https://www.baidu.com')
22 |
23 |
24 | if __name__ == '__main__':
25 | run()
--------------------------------------------------------------------------------
/chapter01/asyncio/cotrast_async.py:
--------------------------------------------------------------------------------
1 | import aiohttp, asyncio, time
2 |
3 |
4 | def take_up_time(func):
5 | def wrapper(*args, **kwargs):
6 | print("开始执行---->")
7 | now = time.time()
8 | result = func(*args, **kwargs)
9 | using = (time.time() - now) * 1000
10 | print(f"结束执行,消耗时间为:{using}ms")
11 | return result
12 |
13 | return wrapper
14 |
15 |
16 | async def request_async():
17 | async with aiohttp.ClientSession() as session:
18 | async with session.get('https://www.baidu.com') as resp:
19 | pass
20 |
21 |
22 | @take_up_time
23 | def run():
24 | tasks = [asyncio.ensure_future(request_async()) for x in range(0, 49)]
25 | loop = asyncio.get_event_loop()
26 | tasks = asyncio.gather(*tasks)
27 | loop.run_until_complete(tasks)
28 |
29 |
30 | if __name__ == '__main__':
31 | run()
32 |
--------------------------------------------------------------------------------
/chapter02/static/css/style.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter02/static/css/style.css
--------------------------------------------------------------------------------
/chapter02/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 | 你好,欢迎您学习Fastapi框架!
10 |
11 |
12 |
13 |
14 | 你好!欢迎您学习Fastapi框架!
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/chapter02/templates/yyy.txt:
--------------------------------------------------------------------------------
1 | asas
2 | sadas
3 | sadasd
4 | sdasd
5 | asdasd
--------------------------------------------------------------------------------
/chapter03/async_sync/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | import threading
6 | import time
7 | import asyncio
8 | app = FastAPI(routes=None)
9 |
10 | @app.get(path="/async")
11 | async def asyncdef():
12 | await asyncio.sleep(10)
13 | print("当前协程运行的线程ID:", threading.current_thread().ident)
14 | return {"index": "async"}
15 |
16 | @app.get(path="/sync")
17 | def syncdef():
18 | time.sleep(10)
19 | print("当前普通函数运行的线程ID:",threading.current_thread().ident)
20 | return {"index": "sync"}
21 |
22 |
23 |
24 |
25 | if __name__ == "__main__":
26 | import uvicorn
27 | import os
28 |
29 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
30 | print(app_modeel_name)
31 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
32 |
--------------------------------------------------------------------------------
/chapter03/background_tasks/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | from starlette.background import BackgroundTasks
6 | import time
7 | app = FastAPI(routes=None)
8 | import asyncio
9 | def send_mail(n):
10 | time.sleep(n)
11 |
12 | @app.api_route(path="/index", methods=["GET", "POST"])
13 | async def index(tasks: BackgroundTasks):
14 | tasks.add_task(send_mail, 10)
15 | print(id(asyncio.get_event_loop()))
16 | return {"index": "index"}
17 |
18 | if __name__ == "__main__":
19 | import uvicorn
20 | import os
21 |
22 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
23 | print(app_modeel_name)
24 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
25 |
--------------------------------------------------------------------------------
/chapter03/close_docs/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | app = FastAPI(
6 | docs_url=None,
7 | redoc_url=None,
8 | # 或者直接设置openapi_url=None
9 | openapi_url=None,
10 | )
11 | if __name__ == "__main__":
12 | import uvicorn
13 | import os
14 |
15 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
16 | print(app_modeel_name)
17 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
18 |
--------------------------------------------------------------------------------
/chapter03/configparser_config/conf.ini:
--------------------------------------------------------------------------------
1 | [fastapi_config]
2 | debug = True
3 | title = "FastAPI"
4 | description = "FastAPI文档明细描述"
5 | version = v1.0.0
6 |
7 | [redis]
8 | ip = 127.0.0.1
9 | port = 6379
10 | password = 123456
--------------------------------------------------------------------------------
/chapter03/configparser_config/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | import configparser
6 |
7 | config = configparser.ConfigParser()
8 | config.read('conf.ini', encoding='utf-8')
9 |
10 | app = FastAPI(
11 | debug=bool(config.get('fastapi_config', 'debug')),
12 | title=config.get('fastapi_config', 'title'),
13 | description=config.get('fastapi_config', 'description'),
14 | version=config.get('fastapi_config', 'version'),
15 | )
16 |
17 | if __name__ == "__main__":
18 | import uvicorn
19 | import os
20 |
21 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
22 | print(app_modeel_name)
23 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
24 |
--------------------------------------------------------------------------------
/chapter03/debugshow/main.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter03/debugshow/main.py
--------------------------------------------------------------------------------
/chapter03/env_config/.env:
--------------------------------------------------------------------------------
1 | DEBUG=true
2 | TITLE="FastAPI"
3 | DESCRIPTION="FastAPI文档明细描述"
4 | vERSION="v1.0.0"
--------------------------------------------------------------------------------
/chapter03/global_exception/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | from starlette.responses import JSONResponse
6 |
7 | async def exception_not_found(request, exc):
8 | return JSONResponse({
9 | "code": exc.status_code,
10 | "error": "没有定义这个请求地址"},
11 | status_code=exc.status_code)
12 |
13 | exception_handlers = {
14 | 404: exception_not_found,
15 | }
16 |
17 | app = FastAPI(exception_handlers=exception_handlers)
18 |
19 |
20 | if __name__ == "__main__":
21 | import uvicorn
22 | import os
23 |
24 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
25 | print(app_modeel_name)
26 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
27 |
--------------------------------------------------------------------------------
/chapter03/more_routers/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | from starlette.responses import JSONResponse
6 |
7 | app = FastAPI()
8 |
9 | # ============多重URL地址绑定函数============
10 | # =========================================
11 | @app.get('/', response_class=JSONResponse)
12 | @app.get('/index', response_class=JSONResponse)
13 | @app.post('/index', response_class=JSONResponse)
14 | @app.get("/app/hello", tags=['app实例对象注册接口-示例'])
15 | def app_hello():
16 | return {"Hello": "app api"}
17 |
18 | # ============同一个URL动态和静态路由==========
19 | # =========================================
20 | # 动态路由
21 | @app.get('/user/{userid}')
22 | async def login(userid: str):
23 | return {"Hello": "dynamic"}
24 |
25 |
26 | # 静态路由
27 | @app.get('/user/userid')
28 | async def login():
29 | return {"Hello": "static"}
30 |
31 |
32 |
33 |
34 | if __name__ == "__main__":
35 | import uvicorn
36 | import os
37 |
38 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
39 | print(app_modeel_name)
40 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
41 |
--------------------------------------------------------------------------------
/chapter03/mount_app/fastapiapp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | from fastapi.responses import JSONResponse
6 |
7 | app = FastAPI(title='主应用',description="我是主应用文档的描述",version="v1.0.0")
8 | @app.get('/index',summary='首页')
9 | async def index():
10 | return JSONResponse({"index": "我是属于主应用的接口!"})
11 |
12 | subapp = FastAPI(title='子应用',description="我是子应用文档的描述",version="v1.0.0")
13 | @subapp.get('/index',summary='首页')
14 | async def index():
15 | return JSONResponse({"index": "我是属于子应用的接口!"})
16 |
17 | app.mount(path='/subapp',app=subapp,name='subapp')
18 |
19 |
20 | if __name__ == "__main__":
21 | import uvicorn
22 | import os
23 |
24 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
25 | print(app_modeel_name)
26 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
27 |
--------------------------------------------------------------------------------
/chapter03/mount_app/flaskapp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | from fastapi.responses import JSONResponse
6 |
7 | app = FastAPI(title='主应用',description="我是主应用文档的描述",version="v1.0.0")
8 | @app.get('/index',summary='首页')
9 | async def index():
10 | return JSONResponse({"index": "我是属于主应用的接口!"})
11 |
12 | subapp = FastAPI(title='子应用',description="我是子应用文档的描述",version="v1.0.0")
13 | @subapp.get('/index',summary='首页')
14 | async def index():
15 | return JSONResponse({"index": "我是属于子应用的接口!"})
16 |
17 | app.mount(path='/subapp',app=subapp,name='subapp')
18 |
19 |
20 | if __name__ == "__main__":
21 | import uvicorn
22 | import os
23 |
24 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
25 | print(app_modeel_name)
26 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
27 |
--------------------------------------------------------------------------------
/chapter03/parameter_cookie/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import List, Optional, Set
4 | from fastapi import FastAPI, Query, Path, Body, Header, Cookie
5 | from starlette import status
6 | from enum import Enum
7 |
8 | from starlette.responses import Response
9 |
10 | app = FastAPI()
11 |
12 |
13 | @app.get("/set_cookie/")
14 | def setcookie(response: Response):
15 | response.set_cookie(key="xiaozhong", value="chengxuyuan-xiaozhongtongxue")
16 | return 'set_cookie ok!'
17 |
18 | @app.get("/get_cookie")
19 | async def Cookier_handel(xiaozhong: Optional[str] = Cookie(None)):
20 | return {
21 | 'xiaozhong':xiaozhong
22 | }
23 |
24 | if __name__ == "__main__":
25 | import uvicorn
26 | import os
27 |
28 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
29 | print(app_modeel_name)
30 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
31 |
--------------------------------------------------------------------------------
/chapter03/parameter_form_and_file/data.bat:
--------------------------------------------------------------------------------
1 | 你好,我是小钟同学。
--------------------------------------------------------------------------------
/chapter03/parameter_request/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import List, Optional, Set
4 | from fastapi import FastAPI, Query, Path, Body, Header, Cookie
5 | from starlette import status
6 | from enum import Enum
7 |
8 | from starlette.responses import Response
9 | from fastapi import Request
10 |
11 | app = FastAPI()
12 |
13 |
14 | @app.get("/get_request/")
15 | async def get_request(request: Request):
16 | form_data= await request.form()
17 | body_data = await request.body()
18 | return {
19 | 'url':request.url,
20 | 'base_url': request.base_url,
21 | 'client_host ': request.client.host,
22 | 'query_params': request.query_params,
23 | 'json_data':await request.json() if body_data else None,
24 | 'form_data':form_data,
25 | 'body_data': body_data,
26 | }
27 |
28 | if __name__ == "__main__":
29 | import uvicorn
30 | import os
31 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
32 | print(app_modeel_name)
33 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
34 |
--------------------------------------------------------------------------------
/chapter03/parameter_response/data.bat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter03/parameter_response/data.bat
--------------------------------------------------------------------------------
/chapter03/parameter_response/main_html_response.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import List, Optional, Set
4 | from fastapi import FastAPI, Query, Path, Body, Header, Cookie
5 | from starlette import status
6 | from enum import Enum
7 |
8 | from starlette.responses import Response, JSONResponse
9 | from fastapi import Request
10 |
11 | app = FastAPI()
12 |
13 |
14 | from fastapi.responses import HTMLResponse
15 |
16 | def generate_html_response():
17 | html_content = """
18 |
19 |
20 | Fastapi框架学习
21 |
22 |
23 | 欢迎学习Fastapi框架!
24 |
25 |
26 | """
27 | return HTMLResponse(content=html_content, status_code=200)
28 |
29 | @app.get("/", response_class=HTMLResponse)
30 | async def index():
31 | return generate_html_response()
32 |
33 | if __name__ == "__main__":
34 | import uvicorn
35 | import os
36 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
37 | print(app_modeel_name)
38 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
39 |
--------------------------------------------------------------------------------
/chapter03/parameter_response/main_json_response.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import List, Optional, Set
4 | from fastapi import FastAPI, Query, Path, Body, Header, Cookie
5 | from starlette import status
6 | from enum import Enum
7 |
8 | from starlette.responses import Response, JSONResponse
9 | from fastapi import Request
10 |
11 | app = FastAPI()
12 |
13 |
14 |
15 | @app.post("/api/v1/json1/")
16 | async def index():
17 | # 默认返回类型就是JSONResponse
18 | return {"code": 0, "msg": "ok", "data": None}
19 |
20 | @app.post("/api/v1/json2/")
21 | async def index():
22 | return JSONResponse(status_code=404, content={"code": 0, "msg": "ok", "data": None})
23 |
24 | if __name__ == "__main__":
25 | import uvicorn
26 | import os
27 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
28 | print(app_modeel_name)
29 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
30 |
--------------------------------------------------------------------------------
/chapter03/parameter_response/main_plain_text_response.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import List, Optional, Set
4 | from fastapi import FastAPI, Query, Path, Body, Header, Cookie
5 | from starlette import status
6 | from enum import Enum
7 |
8 | from starlette.responses import Response, JSONResponse, PlainTextResponse
9 | from fastapi import Request
10 |
11 | app = FastAPI()
12 |
13 |
14 |
15 | @app.post("/api/v1/text1/")
16 | async def index():
17 | return 'ok'
18 |
19 | @app.post("/api/v1/text2/")
20 | async def index():
21 | return PlainTextResponse(status_code=404, content='ok')
22 |
23 | if __name__ == "__main__":
24 | import uvicorn
25 | import os
26 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
27 | print(app_modeel_name)
28 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
29 |
--------------------------------------------------------------------------------
/chapter03/parameter_response/main_redirect_response.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 |
6 | from starlette.responses import HTMLResponse, RedirectResponse
7 |
8 |
9 | app = FastAPI()
10 |
11 |
12 |
13 | @app.get("/baidu", response_class=HTMLResponse)
14 | async def index():
15 | # 外部地址重定向
16 | return RedirectResponse("https://wwww.baidu.com")
17 |
18 | @app.get("/redirect1")
19 | async def index():
20 | # 内部地址重定向
21 | return RedirectResponse("/index",status_code=301)
22 |
23 |
24 | @app.get("/redirect2")
25 | async def index():
26 | # 内部地址重定向
27 | return RedirectResponse("/index",status_code=302)
28 |
29 | @app.get("/index")
30 | async def index():
31 | return {
32 | 'code':200,
33 | 'messgaee':'重定向成功'
34 | }
35 |
36 | if __name__ == "__main__":
37 | import uvicorn
38 | import os
39 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
40 | print(app_modeel_name)
41 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
42 |
--------------------------------------------------------------------------------
/chapter03/parameter_response/main_xml_response.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import List, Optional, Set
4 | from fastapi import FastAPI, Query, Path, Body, Header, Cookie
5 | from starlette import status
6 | from enum import Enum
7 |
8 | from starlette.responses import Response
9 | from fastapi import Request
10 |
11 | app = FastAPI()
12 |
13 | @app.get("/xml/")
14 | def get_xml_data():
15 | data = """
16 |
17 | George
18 | John
19 | Reminder
20 | Don't forget the meeting!
21 |
22 | """
23 | return Response(content=data, media_type="application/xml")
24 |
25 | if __name__ == "__main__":
26 | import uvicorn
27 | import os
28 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
29 | print(app_modeel_name)
30 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
31 |
--------------------------------------------------------------------------------
/chapter03/startup_shutdown/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 |
4 | from fastapi import FastAPI
5 | from starlette.background import BackgroundTasks
6 | import time
7 |
8 | app = FastAPI()
9 |
10 | # 生命周期异步上下文管理器处理程序代替单独的启动和关闭处理程序
11 | @app.on_event("startup")
12 | async def startup_event_async():
13 | print("服务进程启动成功-async函数")
14 |
15 | @app.on_event("startup")
16 | def startup_event_sync():
17 | print("服务进程启动成功-sync函数")
18 |
19 | @app.on_event("shutdown")
20 | async def shutdown_event_async():
21 | print("服务进程已关闭-async函数")
22 |
23 |
24 | @app.on_event("shutdown")
25 | def shutdown_event_sync():
26 | print("服务进程已关闭-sync函数")
27 |
28 | if __name__ == "__main__":
29 | import uvicorn
30 | import os
31 |
32 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
33 | print(app_modeel_name)
34 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
35 |
--------------------------------------------------------------------------------
/chapter04/custom_exception/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from fastapi import Request
4 | from fastapi import FastAPI, Query, HTTPException
5 | from starlette.responses import JSONResponse
6 |
7 | app = FastAPI()
8 |
9 |
10 | class CustomException(Exception):
11 | def __init__(self, message: str):
12 | self.message = message
13 |
14 |
15 | @app.exception_handler(CustomException)
16 | async def custom_exception_handler(request: Request, exc: CustomException):
17 | return JSONResponse(content={"message": exc.message}, )
18 |
19 |
20 | @app.get("/custom_exception")
21 | async def read_unicorn(name: str = 'zhong'):
22 | if name == "zhong":
23 | raise CustomException(message='抛出自定义异常')
24 | return {"name": name}
25 |
26 |
27 | if __name__ == "__main__":
28 | import uvicorn
29 | import os
30 |
31 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
32 | print(app_modeel_name)
33 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
34 |
--------------------------------------------------------------------------------
/chapter04/request_validation_error/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from fastapi import Request
4 | from fastapi import FastAPI, Query, HTTPException
5 | from fastapi.exceptions import RequestValidationError
6 | from starlette.responses import JSONResponse
7 | from fastapi import FastAPI, WebSocket, WebSocketDisconnect
8 |
9 | app = FastAPI()
10 |
11 | @app.exception_handler(RequestValidationError)
12 | async def validation_exception_handler(request, exc):
13 | return JSONResponse({'mes':'触发了RequestValidationError错误,,错误信息:%s !'%(str(exc))})
14 |
15 |
16 | @app.get("/request_exception/")
17 | async def request_exception(user_id: int):
18 | return {"user_id": user_id}
19 |
20 |
21 | @app.websocket("/ws/{user}")
22 | async def websocket_endpoint(websocket: WebSocket, user: str):
23 | pass
24 | websocket.query_params
25 |
26 | if __name__ == "__main__":
27 | import uvicorn
28 | import os
29 |
30 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
31 | print(app_modeel_name)
32 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
33 |
--------------------------------------------------------------------------------
/chapter05/pydantic_field/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from decimal import Decimal
4 | from typing import Union, Optional, List
5 |
6 | from pydantic import BaseModel, Field
7 |
8 |
9 | class User(BaseModel):
10 | name: str = Field(..., title='姓名', description='姓名字段需要长度大于6且小于等于12', max_length=12, min_length=6, example="Foo")
11 | age: int = Field(..., title='年龄', description='年龄需要大于18岁', ge=18, example=12)
12 | password: str = Field(..., title='密码', description='密码需要长度大于6', gl=6, example=6)
13 | tax: Optional[float] = Field(None, example=3.2)
14 |
15 | if __name__ == '__main__':
16 | user=User(name='xiaozhong',age=18,password='xxxxxxxxxxx')
17 | print(user.name)
18 | print(user.age)
19 | print(user.password)
20 |
--------------------------------------------------------------------------------
/chapter05/pydantic_validator/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import Union, Optional, List
4 |
5 | from pydantic import BaseModel, validator, ValidationError
6 |
7 |
8 | class Person(BaseModel):
9 | username: str
10 | password: str
11 |
12 | # '*' 在这里是匹配任意字段
13 | @validator('*', pre=True)
14 | def split(cls, v,):
15 | """如果传参是字符串,根据逗号切割成list"""
16 | if isinstance(v, str):
17 | return v.split(',')
18 | return v
19 |
20 |
21 | if __name__ == '__main__':
22 | try:
23 | user = Person(username='xiaozhong', password='123456')
24 | except ValidationError as e:
25 | print(e.errors())
26 | print(e.json())
27 | else:
28 | print(user.username, user.password)
29 |
--------------------------------------------------------------------------------
/chapter05/pydantic_validator/root_validator_main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import Dict
4 |
5 | from pydantic import BaseModel, validator, ValidationError, PydanticValueError
6 |
7 | from pydantic import BaseModel, ValidationError, root_validator
8 |
9 |
10 | class User(BaseModel):
11 | username: str
12 | password_old: str
13 | password_new: str
14 |
15 | @root_validator
16 | def check_passwords(cls, values):
17 | password_old, password_new = values.get('password_old'), values.get('password_new')
18 | # 新旧号码的确认匹配处理
19 | if password_old and password_new and password_old != password_new:
20 | raise ValueError('passwords do not match')
21 | return values
22 |
23 | if __name__ == '__main__':
24 | try:
25 | user = User(username='xiaozhong', password_old='123456', password_new='123456_')
26 | except ValidationError as e:
27 | print(e.errors())
28 | else:
29 | print(user.username, user.password_old)
30 |
--------------------------------------------------------------------------------
/chapter05/pydantic_validator/share_logic_auth_main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import Union, Optional, List
4 |
5 | from pydantic import BaseModel, validator, ValidationError
6 |
7 | from pydantic import BaseModel, validator
8 |
9 |
10 | def share_logic_auth(name: str) -> str:
11 | if name == "xiaozhong":
12 | return "通过"
13 | return "不通过"
14 |
15 |
16 | class Base(BaseModel):
17 | name: str
18 | # 定义校验器
19 | _validator_name = validator("name", allow_reuse=True)(share_logic_auth)
20 |
21 |
22 | class Yuser(Base):
23 | pass
24 |
25 |
26 | class Xuser(Base):
27 | pass
28 |
29 |
30 | yuser = Yuser(name='xiaozhong')
31 | print("xiaozhong:名字",yuser.name)
32 | xuser = Xuser(name='_xiao')
33 | print("_xiao:名字",xuser.name)
34 |
35 |
--------------------------------------------------------------------------------
/chapter05/pydantic_validator_order/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | from typing import Dict
4 |
5 | from pydantic import BaseModel, validator, ValidationError
6 |
7 |
8 | class Person(BaseModel):
9 | username: str
10 | address: Dict
11 |
12 | @validator("address",pre=True)
13 | def adress_rule(cls, address):
14 | # 如果地址长度小于6,那么则返回
15 | if len(address) < 6:
16 | raise ValueError("地址长度不能小于6")
17 | elif len(address) > 12:
18 | raise ValueError("地址长度不能大于12")
19 | return address
20 |
21 | if __name__ == '__main__':
22 | try:
23 | user = Person(username='xiaozhong', address='12345')
24 | except ValidationError as e:
25 | print(e.errors())
26 | else:
27 | print(user.username, user.address)
--------------------------------------------------------------------------------
/chapter06/depend_class/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI, Request, Body
2 | from fastapi import Query, Depends
3 | from fastapi.exceptions import HTTPException
4 |
5 | from fastapi import FastAPI
6 | from fastapi import Query, Depends
7 | from fastapi.exceptions import HTTPException
8 |
9 |
10 | app = FastAPI()
11 |
12 | class UsernameCheck:
13 | def __init__(self, username:str=Query(...)):
14 | if username != 'zhong':
15 | raise HTTPException(status_code=403, detail="没有权限访问")
16 | self.username = username
17 |
18 |
19 | @app.get("/user/login/")
20 | def user_login(username: UsernameCheck = Depends(UsernameCheck)):
21 | return username
22 |
23 |
24 | @app.get("/user/info")
25 | def user_info(username: UsernameCheck = Depends(UsernameCheck)):
26 | return username
27 |
28 |
29 | if __name__ == "__main__":
30 | import uvicorn
31 | import os
32 |
33 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
34 | print(app_modeel_name)
35 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
36 |
--------------------------------------------------------------------------------
/chapter06/depend_func/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI, Request, Body
2 | from fastapi import Query, Depends
3 | from fastapi.exceptions import HTTPException
4 |
5 | from fastapi import FastAPI
6 | from fastapi import Query, Depends
7 | from fastapi.exceptions import HTTPException
8 |
9 |
10 | app = FastAPI()
11 |
12 | def username_check(username:str=Query(...)):
13 | if username != 'zhong':
14 | raise HTTPException(status_code=403, detail="没有权限访问")
15 | return username
16 |
17 |
18 | @app.get("/user/login/")
19 | def user_login(username: str = Depends(username_check)):
20 | return username
21 |
22 |
23 | @app.get("/user/info")
24 | def user_info(username: str = Depends(username_check)):
25 | return username
26 |
27 |
28 | if __name__ == "__main__":
29 | import uvicorn
30 | import os
31 |
32 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
33 | print(app_modeel_name)
34 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
35 |
--------------------------------------------------------------------------------
/chapter07/cors_middleware/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from fastapi.middleware.cors import CORSMiddleware
3 |
4 | app = FastAPI()
5 |
6 | origins = [
7 | "http://localhost.baidu.com",
8 | "https://localhost.qq.com",
9 | "http://localhost",
10 | "http://localhost:8080",
11 | ]
12 |
13 | # 添加自定义中间件
14 | app.add_middleware(
15 | CORSMiddleware,
16 | allow_origins=origins,
17 | allow_credentials=True,
18 | allow_methods=["*"],
19 | allow_headers=["*"],
20 | )
21 |
22 |
23 | @app.get("/")
24 | async def main():
25 | return {"message": "Hello World"}
26 |
27 |
28 |
29 | if __name__ == "__main__":
30 | import uvicorn
31 | import os
32 |
33 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
34 | print(app_modeel_name)
35 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
36 |
--------------------------------------------------------------------------------
/chapter07/https_redirect_middleware/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from fastapi.middleware.cors import CORSMiddleware
3 | from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
4 |
5 | app = FastAPI()
6 |
7 |
8 | app.add_middleware(HTTPSRedirectMiddleware)
9 |
10 | @app.get("/index")
11 | async def httpsredirec():
12 | return {
13 | 'code':200
14 | }
15 |
16 |
17 | if __name__ == "__main__":
18 | import uvicorn
19 | import os
20 |
21 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
22 | print(app_modeel_name)
23 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
24 |
--------------------------------------------------------------------------------
/chapter07/middleware_process_time/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI, Request
2 | import time
3 |
4 | app = FastAPI()
5 |
6 |
7 | @app.middleware("http")
8 | async def add_process_time_header(request: Request, call_next):
9 | # 定义请求处理时间
10 | start_time = time.time()
11 | response = await call_next(request)
12 | process_time = time.time() - start_time
13 | # 添加响应头
14 | response.headers["X-Process-Time"] = str(process_time)
15 | return response
16 |
17 |
18 | @app.get("/index")
19 | async def index():
20 | return {
21 | 'code': 200
22 | }
23 |
24 |
25 | if __name__ == "__main__":
26 | import uvicorn
27 | import os
28 |
29 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
30 | print(app_modeel_name)
31 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
32 |
--------------------------------------------------------------------------------
/chapter07/trusted_host_middleware/main.py:
--------------------------------------------------------------------------------
1 | from fastapi.middleware.trustedhost import TrustedHostMiddleware
2 | from fastapi import FastAPI
3 | from starlette.middleware.gzip import GZipMiddleware
4 |
5 | app = FastAPI()
6 |
7 | app.add_middleware(TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"])
8 |
9 | @app.get("/index")
10 | async def truste():
11 | return {
12 | 'code':200
13 | }
14 |
15 | from fastapi import FastAPI
16 | app.add_middleware(GZipMiddleware, minimum_size=1000)
17 |
18 | app = FastAPI()
19 |
20 | @app.get("/index")
21 | async def gzip():
22 | return {
23 | 'code':200
24 | }
25 |
26 | if __name__ == "__main__":
27 | import uvicorn
28 | import os
29 |
30 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
31 | print(app_modeel_name)
32 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
33 |
--------------------------------------------------------------------------------
/chapter08/databases_sql/user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/databases_sql/user.db
--------------------------------------------------------------------------------
/chapter08/databases_sqlalchemy/user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/databases_sqlalchemy/user.db
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/alembic/README:
--------------------------------------------------------------------------------
1 | Generic single-database configuration.
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/alembic/script.py.mako:
--------------------------------------------------------------------------------
1 | """${message}
2 |
3 | Revision ID: ${up_revision}
4 | Revises: ${down_revision | comma,n}
5 | Create Date: ${create_date}
6 |
7 | """
8 | from alembic import op
9 | import sqlalchemy as sa
10 | ${imports if imports else ""}
11 |
12 | # revision identifiers, used by Alembic.
13 | revision = ${repr(up_revision)}
14 | down_revision = ${repr(down_revision)}
15 | branch_labels = ${repr(branch_labels)}
16 | depends_on = ${repr(depends_on)}
17 |
18 |
19 | def upgrade():
20 | ${upgrades if upgrades else "pass"}
21 |
22 |
23 | def downgrade():
24 | ${downgrades if downgrades else "pass"}
25 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/alembic/versions/287a3cf31b84_shann.py:
--------------------------------------------------------------------------------
1 | """SHANn
2 |
3 | Revision ID: 287a3cf31b84
4 | Revises: 3328ff109aa7
5 | Create Date: 2022-04-04 12:26:15.416620
6 |
7 | """
8 | from alembic import op
9 | import sqlalchemy as sa
10 |
11 |
12 | # revision identifiers, used by Alembic.
13 | revision = '287a3cf31b84'
14 | down_revision = '3328ff109aa7'
15 | branch_labels = None
16 | depends_on = None
17 |
18 |
19 | def upgrade():
20 | # ### commands auto generated by Alembic - please adjust! ###
21 | op.drop_column('users', 'addr')
22 | # ### end Alembic commands ###
23 |
24 |
25 | def downgrade():
26 | # ### commands auto generated by Alembic - please adjust! ###
27 | op.add_column('users', sa.Column('addr', sa.VARCHAR(length=50), nullable=True))
28 | # ### end Alembic commands ###
29 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/alembic/versions/3328ff109aa7_add_mobile.py:
--------------------------------------------------------------------------------
1 | """add mobile
2 |
3 | Revision ID: 3328ff109aa7
4 | Revises:
5 | Create Date: 2022-04-04 12:24:42.862656
6 |
7 | """
8 | from alembic import op
9 | import sqlalchemy as sa
10 |
11 |
12 | # revision identifiers, used by Alembic.
13 | revision = '3328ff109aa7'
14 | down_revision = None
15 | branch_labels = None
16 | depends_on = None
17 |
18 |
19 | def upgrade():
20 | # ### commands auto generated by Alembic - please adjust! ###
21 | op.add_column('users', sa.Column('addr', sa.String(length=50), nullable=True))
22 | # ### end Alembic commands ###
23 |
24 |
25 | def downgrade():
26 | # ### commands auto generated by Alembic - please adjust! ###
27 | op.drop_column('users', 'addr')
28 | # ### end Alembic commands ###
29 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/api/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 19:59
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/config/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:05
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/db/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:00
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/db/database.py:
--------------------------------------------------------------------------------
1 | # 导入异步引擎的模块
2 | from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
3 | from sqlalchemy.orm import declarative_base, sessionmaker
4 | # URL地址格式
5 | from config.confiig import get_settings
6 | # 创建异步引擎对象
7 | async_engine = create_async_engine(get_settings().ASYNC_DATABASE_URI, echo=False)
8 | # 创建ORM模型基类
9 | Base = declarative_base()
10 | # 创建异步的会话管理对象
11 | SessionLocal = sessionmaker(bind=async_engine, expire_on_commit=False, class_=AsyncSession)
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/models/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:00
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 | from .user import *
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/models/user.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 |
4 | from db.database import Base
5 | from sqlalchemy import Column, Integer, String
6 |
7 | class User(Base):
8 | # 指定本类映射到users表
9 | __tablename__ = 'users'
10 | id = Column(Integer, primary_key=True, autoincrement=True)
11 | name = Column(String(20))
12 | nikename = Column(String(32))
13 | password = Column(String(32))
14 | email = Column(String(50))
15 | # 新增手机号码字段
16 | mobile = Column(String(50))
17 | # 新增手机号码字段
18 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 22:32
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/servies/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:00
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter08/fastapi_sqlalchemy/user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/fastapi_sqlalchemy/user.db
--------------------------------------------------------------------------------
/chapter08/lua_register_script/mian.py:
--------------------------------------------------------------------------------
1 | import time
2 | from uuid import uuid4
3 |
4 | from redis import Redis
5 |
6 | # 创建连接客户端对象
7 | redis = Redis(host="localhost",port=6379)
8 | # 封装获取锁的值和删除锁操作的Lua脚本script内容
9 | script = """
10 | if redis.call('GET', KEYS[1]) == ARGV[1] then
11 | return redis.call('DEL', KEYS[1])
12 | else
13 | return 0
14 | end
15 | """
16 |
17 |
18 | def action(lock_name='pay_order',client_signature=str(uuid4())):
19 | if redis.set(name=lock_name, value=client_signature, nx=True, ex=25): # 锁不存在才能上锁成功,过期时间应为业务时间的五倍,此处故意写小,模拟过期释放
20 | try:
21 | print('处理业务', client_signature)
22 | time.sleep(10)
23 | except Exception as e:
24 | print(e)
25 | finally:
26 | # 释放锁
27 | cmd = redis.register_script(script)
28 | res = cmd(keys=[lock_name], args=[client_signature]) # 执行脚本
29 | if res:
30 | print('锁已释放')
31 | else:
32 | print('不是自己的锁')
33 | else:
34 | print('锁已存在')
35 |
36 |
37 | if __name__ == '__main__':
38 | action()
39 |
--------------------------------------------------------------------------------
/chapter08/sql_model/main.py:
--------------------------------------------------------------------------------
1 | from sqlmodel import create_engine
2 | ASYNC_DATABASE_URI = "sqlite+aiosqlite:///aiosqlite_user.db"
3 | engine = create_engine(ASYNC_DATABASE_URI)
--------------------------------------------------------------------------------
/chapter08/sqlalchemy_async_sqlite3/aiosqlite_user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/sqlalchemy_async_sqlite3/aiosqlite_user.db
--------------------------------------------------------------------------------
/chapter08/sqlalchemy_sync_sqlite3/user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/sqlalchemy_sync_sqlite3/user.db
--------------------------------------------------------------------------------
/chapter08/sqlite3_connect/main.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | connection = sqlite3.connect('test.db')
4 | # 创建游标
5 | cursor = connection.cursor()
6 | # 创建表
7 | cursor.execute('''CREATE TABLE user
8 | (id INT PRIMARY KEY NOT NULL,
9 | username TEXT NOT NULL,
10 | password TEXT NOT NULL);''')
11 | # 数据保存
12 | cursor.execute("INSERT INTO user (id,username,password) VALUES (1, 'xiaozhong', '123456')")
13 | cursor.execute("INSERT INTO user (id,username,password) VALUES (2, 'muyu', '123456')")
14 | # 数据查询
15 | cursor = cursor.execute("SELECT id, username, password from user")
16 | for row in cursor:
17 | print(row)
18 | connection.commit()
19 | # 数据更新
20 | cursor.execute("UPDATE user set username ='xiaoxiao' where id = 1")
21 | connection.commit()
22 | # 数据删除
23 | cursor.execute("DELETE from user where id=1;")
24 | connection.commit()
25 | # 关闭数据库连接
26 | connection.close()
27 |
--------------------------------------------------------------------------------
/chapter08/sqlite3_connect/test.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/sqlite3_connect/test.db
--------------------------------------------------------------------------------
/chapter08/sqlmodel_async_sqlite3/aiosqlite_user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/sqlmodel_async_sqlite3/aiosqlite_user.db
--------------------------------------------------------------------------------
/chapter08/sqlmodel_sync_sqlite3/user.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter08/sqlmodel_sync_sqlite3/user.db
--------------------------------------------------------------------------------
/chapter09/jwt_use/main.py:
--------------------------------------------------------------------------------
1 | from datetime import timedelta
2 | from jose import jwt
3 | from datetime import datetime
4 |
5 |
6 | SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
7 | ALGORITHM = "HS256"
8 | ACCESS_TOKEN_EXPIRE_MINUTES = 30
9 | REFRRSH_ACCESS_TOKEN_EXPIRE_MINUTES = 70
10 |
11 |
12 | class TokenUtils:
13 |
14 | @staticmethod
15 | def token_encode(data):
16 | jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
17 | return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
18 |
19 | @staticmethod
20 | def token_decode(token):
21 | return jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
22 |
23 |
24 | data = {
25 | 'iss ': "xiaozhong",
26 | 'sub': 'xiaozhongtongxue',
27 | 'name': 'superadmin',
28 | 'admin': True,
29 | 'exp': datetime.utcnow() + timedelta(minutes=15)
30 | }
31 |
32 |
33 | token = TokenUtils.token_encode(data=data)
34 | print(token)
35 | payload = TokenUtils.token_decode(token =token)
36 | print(payload)
37 |
--------------------------------------------------------------------------------
/chapter09/mode_code/get_token.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 |
3 | # 定义我们的APP服务对象
4 | app = FastAPI()
5 |
6 |
7 | @app.get("/get/access_token")
8 | async def access_token(code: str):
9 | import requests
10 | # 第三方服务端请求授权服务器获取access_token的地址
11 | rsp = requests.get(f"http://127.0.0.1:8000/oauth2/authorize/access_token?client_id=xiaozhong&client_secret=123456&code={code}").json()
12 | access_token = rsp.get('access_token')
13 | refresh_token = rsp.get('refresh_token')
14 | access_token_expires = rsp.get('expires_in')
15 | username = rsp.get('userid')
16 | return {
17 | "access_token": access_token,
18 | # access_token接口调用凭证超时时间
19 | "expires_in": access_token_expires,
20 | "refresh_token": refresh_token,
21 | "token_type": "bearer",
22 | "userid": username,
23 | "scope": "SCOPE"
24 | }
25 |
26 |
27 | if __name__ == '__main__':
28 | import uvicorn
29 | uvicorn.run('get_token:app', host="127.0.0.1", port=8100, debug=True, reload=True)
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/api/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 19:59
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/api/short.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter, Depends,BackgroundTasks
2 | from fastapi.responses import RedirectResponse, PlainTextResponse
3 | from dependencies import get_db_session
4 | from db.database import AsyncSession
5 | from servies.short import ShortServeries
6 |
7 | router_short = APIRouter(tags=["短链访问"])
8 |
9 |
10 | @router_short.get('/{short_tag}')
11 | async def short_redirect(*,short_tag: str, db_session: AsyncSession = Depends(get_db_session),taks:BackgroundTasks):
12 | data = await ShortServeries.get_short_url(db_session, short_tag)
13 | if not data:
14 | return PlainTextResponse("没有对应短链信息记录")
15 | data.visits_count=data.visits_count+1
16 | taks.add_task(ShortServeries.update_short_url,db_session,short_url_id=data.id,visits_count=data.visits_count)
17 | return RedirectResponse(url=data.long_url)
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/config/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:05
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/db/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:00
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/db/database.py:
--------------------------------------------------------------------------------
1 | # 导入异步引擎的模块
2 | from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
3 | from sqlalchemy.orm import declarative_base, sessionmaker
4 | # URL地址格式
5 | from config.config import get_settings
6 | # 创建异步引擎对象
7 | async_engine = create_async_engine(get_settings().ASYNC_DATABASE_URI, echo=False)
8 | # 创建ORM模型基类
9 | Base = declarative_base()
10 | # 创建异步的会话管理对象
11 | SessionLocal = sessionmaker(bind=async_engine, expire_on_commit=False, class_=AsyncSession)
12 |
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/models/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:00
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
35 |
36 | from .model import User
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/models/model.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 |
4 | from db.database import Base
5 | from sqlalchemy import Column, Integer, String, DateTime, func
6 |
7 |
8 | class User(Base):
9 | # 指定本类映射到users表
10 | __tablename__ = 'user'
11 | id = Column(Integer, primary_key=True, autoincrement=True)
12 | # 用户姓名
13 | username = Column(String(20))
14 | # 用户密码
15 | password = Column(String(32))
16 | # 用户创建时间
17 | created_at = Column(DateTime(), default=func.now())
18 |
19 | class ShortUrl(Base):
20 | # 指定本类映射到users表
21 | __tablename__ = 'short_url'
22 | id = Column(Integer, primary_key=True, autoincrement=True)
23 | # 短链标签
24 | short_tag = Column(String(20),nullable=False)
25 | # 短连接地址
26 | short_url = Column(String(20))
27 | # 长链接地址
28 | long_url = Column(String, nullable=False)
29 | # 访问次数
30 | visits_count= Column(Integer, nullable=True)
31 | # 短链创建时间
32 | created_at = Column(DateTime(), default=func.now())
33 | # 短链创建时间
34 | created_by = Column(String(20))
35 | # 短信内容
36 | msg_context = Column(String, nullable=False)
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 22:32
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/servies/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # coding=utf-8
3 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +
4 | # ┏┓ ┏┓+ +
5 | # ┏┛┻━━━┛┻┓ + +
6 | # ┃ ┃
7 | # ┃ ━ ┃ ++ + + +
8 | # ████━████ ┃+
9 | # ┃ ┃ +
10 | # ┃ ┻ ┃
11 | # ┃ ┃ + +
12 | # ┗━┓ ┏━┛
13 | # ┃ ┃
14 | # ┃ ┃ + + + +
15 | # ┃ ┃ Codes are far away from bugs with the animal protecting
16 | # ┃ ┃ + 神兽保佑,代码无bug
17 | # ┃ ┃
18 | # ┃ ┃ +
19 | # ┃ ┗━━━┓ + +
20 | # ┃ ┣┓
21 | # ┃ ┏┛
22 | # ┗┓┓┏━┳┓┏┛ + + + +
23 | # ┃┫┫ ┃┫┫
24 | # ┗┻┛ ┗┻┛+ + + +
25 | # + + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + ++ + + +"""
26 | """
27 | Author = zyx
28 | @Create_Time: 2022/4/3 20:00
29 | @version: v1.0.0
30 | @Contact: 308711822@qq.com
31 | @File: __init__.py.py
32 | @文件功能描述:------
33 | """
34 |
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/short.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/shorr_url_pro/short.db
--------------------------------------------------------------------------------
/chapter10/shorr_url_pro/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/shorr_url_pro/utils/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/api/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/api/short.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter, Depends,BackgroundTasks
2 | from fastapi.responses import RedirectResponse, PlainTextResponse
3 |
4 | from dependencies import get_db_session
5 | from db.database import AsyncSession
6 | from servies.short import ShortServeries
7 |
8 | router_short = APIRouter(tags=["短链访问"])
9 |
10 |
11 | @router_short.get('/{short_tag}')
12 | async def short_redirect(*,short_tag: str, db_session: AsyncSession = Depends(get_db_session),taks:BackgroundTasks):
13 | data = await ShortServeries.get_short_url(db_session, short_tag)
14 | if not data:
15 | return PlainTextResponse("没有对应短链信息记录")
16 | data.visits_count=data.visits_count+1
17 | taks.add_task(ShortServeries.update_short_url,db_session,short_url_id=data.id,visits_count=data.visits_count)
18 | return RedirectResponse(url=data.long_url)
19 |
20 |
21 |
--------------------------------------------------------------------------------
/chapter10/short_url_pro/app.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from api.short import router_short
3 | from api.user import router_uesr
4 | app = FastAPI(title='fastapi集成短链实战案例')
5 |
6 | @app.on_event("startup")
7 | async def startup_event():
8 | pass
9 | from db.database import async_engine, Base
10 | from models.model import User,ShortUrl
11 | async def init_create_table():
12 | async with async_engine.begin() as conn:
13 | # await conn.run_sync(Base.metadata.drop_all)
14 | await conn.run_sync(Base.metadata.create_all)
15 | await init_create_table()
16 |
17 | @app.on_event("shutdown")
18 | async def shutdown_event():
19 | pass
20 |
21 | from api.short import router_short
22 | from api.user import router_uesr
23 | app.include_router(router_short)
24 | app.include_router(router_uesr)
25 |
26 | print('启动!')
27 | if __name__ == '__main__':
28 | import uvicorn
29 | uvicorn.run(app='app:app', host="127.0.0.1", port=8000, reload=True)
--------------------------------------------------------------------------------
/chapter10/short_url_pro/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/config/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/config/config.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseSettings
2 | from functools import lru_cache
3 |
4 | class Settings(BaseSettings):
5 | # 定义连接异步引擎数据库的URL地址
6 | ASYNC_DATABASE_URI: str = "sqlite+aiosqlite:///short.db"
7 | # 定义TOEKN的签名信息值
8 | TOKEN_SIGN_SECRET:str = 'ZcjT6Rcp1yIFQoS7'
9 |
10 | @lru_cache()
11 | def get_settings():
12 | return Settings()
13 |
--------------------------------------------------------------------------------
/chapter10/short_url_pro/db/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/db/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/db/database.py:
--------------------------------------------------------------------------------
1 | # 导入异步引擎的模块
2 | from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
3 | from sqlalchemy.orm import declarative_base, sessionmaker
4 | # URL地址格式
5 | from config.config import get_settings
6 | # 创建异步引擎对象
7 | async_engine = create_async_engine(get_settings().ASYNC_DATABASE_URI, echo=False)
8 | # 创建ORM模型基类
9 | Base = declarative_base()
10 | # 创建异步的会话管理对象
11 | SessionLocal = sessionmaker(bind=async_engine, expire_on_commit=False, class_=AsyncSession)
--------------------------------------------------------------------------------
/chapter10/short_url_pro/dependencies/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy.exc import SQLAlchemyError
2 | from sqlalchemy.ext.asyncio import AsyncSession
3 | from typing import AsyncGenerator
4 | from db.database import SessionLocal
5 |
6 | async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
7 | db_session = None
8 | try:
9 | db_session = SessionLocal()
10 | yield db_session
11 | finally:
12 | await db_session.close()
13 |
14 | from contextlib import asynccontextmanager
15 | @asynccontextmanager
16 | async def get_db_session_asynccont() -> AsyncGenerator:
17 | async_session = SessionLocal()
18 | try:
19 | yield async_session
20 | await async_session.commit()
21 | except SQLAlchemyError as ex:
22 | await async_session.rollback()
23 | raise ex
24 | finally:
25 | await async_session.close()
--------------------------------------------------------------------------------
/chapter10/short_url_pro/main.py:
--------------------------------------------------------------------------------
1 | from app import app
2 | if __name__ == '__main__':
3 | import uvicorn
4 |
5 | uvicorn.run(app='main:app', host="127.0.0.1", port=8000)
--------------------------------------------------------------------------------
/chapter10/short_url_pro/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/models/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/models/model.py:
--------------------------------------------------------------------------------
1 | from db.database import Base
2 | from sqlalchemy import Column, String, DateTime, func,Integer#Integer
3 |
4 | class User(Base):
5 | # 指定本类映射到users表
6 | __tablename__ = 'user'
7 | id = Column(Integer, primary_key=True, autoincrement=True)
8 | # 用户姓名
9 | username = Column(String(20))
10 | # 用户密码
11 | password = Column(String(32))
12 | # 用户创建时间
13 | created_at = Column(DateTime(), default=func.now())
14 |
15 | class ShortUrl(Base):
16 | # 指定本类映射到users表
17 | __tablename__ = 'short_url'
18 | id = Column(Integer, primary_key=True, autoincrement=True)
19 | # 短链标签
20 | short_tag = Column(String(20),nullable=False)
21 | # 短连接地址
22 | short_url = Column(String(20))
23 | # 长链接地址
24 | long_url = Column(String, nullable=False)
25 | # 访问次数
26 | visits_count= Column(Integer, nullable=True)
27 | # 短链创建时间
28 | created_at = Column(DateTime(), default=func.now())
29 | # 短链创建时间
30 | created_by = Column(String(20))
31 | # 短信内容
32 | msg_context = Column(String, nullable=False)
--------------------------------------------------------------------------------
/chapter10/short_url_pro/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 | class SingleShortUrlCreate(BaseModel):
4 | """
5 | 创建新短链记录时候需要传递参数信息
6 | """
7 | # 需要生成长链接地址
8 | long_url:str
9 | # 群发短信内容
10 | msg_context:str
11 | # 短连接生成前缀
12 | short_url:str = "http://127.0.0.1:8000/"
13 | # 访问次数-默认值是0
14 | visits_count:int = 0
15 | # 短链标签-默认可以不传
16 | short_tag:str = ""
17 | # 默认不传-通常后端进行生成处理
18 | created_by = ""
19 |
20 |
--------------------------------------------------------------------------------
/chapter10/short_url_pro/servies/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/servies/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/servies/short.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/servies/short.db
--------------------------------------------------------------------------------
/chapter10/short_url_pro/short.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/short.db
--------------------------------------------------------------------------------
/chapter10/short_url_pro/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter10/short_url_pro/utils/__init__.py
--------------------------------------------------------------------------------
/chapter10/short_url_pro/utils/passlib_hepler.py:
--------------------------------------------------------------------------------
1 | from passlib.context import CryptContext
2 |
3 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
4 |
5 |
6 | class PasslibHelper:
7 | pass
8 |
9 | # plain_password 明文密码,hashed_password哈希密码
10 | @staticmethod
11 | def verity_password(plain_password: str, hashed_password: str):
12 | """对密码进行校验"""
13 | return pwd_context.verify(plain_password, hashed_password)
14 |
15 | # 进行哈希 密码加密
16 | @staticmethod
17 | def hash_password(password: str) -> str:
18 | return pwd_context.hash(password)
19 |
20 | if __name__ == '__main__':
21 | print(PasslibHelper.hash_password("123456"))
--------------------------------------------------------------------------------
/chapter10/short_url_pro/utils/random_helper.py:
--------------------------------------------------------------------------------
1 | import string
2 | import random
3 |
4 |
5 |
6 | def generate_short_url(size=7) -> str:
7 | letters = string.ascii_letters + string.digits
8 | short_tag = ''.join(random.choice(letters) for i in range(size))
9 | return short_tag
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/api/__init__.py
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/chat.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/chat.db
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/config/__init__.py
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/config/config.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseSettings
2 | from functools import lru_cache
3 |
4 | class Settings(BaseSettings):
5 | # 定义连接异步引擎数据库的URL地址
6 | ASYNC_DATABASE_URI: str = "sqlite+aiosqlite:///chat.db"
7 | # 定义TOEKN的签名信息值
8 | TOKEN_SIGN_SECRET:str = 'ZcjT6Rcp1yIFQoS7'
9 |
10 | @lru_cache()
11 | def get_settings():
12 | return Settings()
13 |
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/db/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/db/__init__.py
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/db/database.py:
--------------------------------------------------------------------------------
1 | # 导入异步引擎的模块
2 | from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
3 | from sqlalchemy.orm import declarative_base, sessionmaker
4 | # URL地址格式
5 | from config.config import get_settings
6 | # 创建异步引擎对象
7 | async_engine = create_async_engine(get_settings().ASYNC_DATABASE_URI, echo=False)
8 | # 创建ORM模型基类
9 | Base = declarative_base()
10 | # 创建异步的会话管理对象
11 | SessionLocal = sessionmaker(bind=async_engine, expire_on_commit=False, class_=AsyncSession)
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/dependencies/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy.ext.asyncio import AsyncSession
2 | from typing import AsyncGenerator
3 | from db.database import SessionLocal
4 |
5 | async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
6 | db_session = None
7 | try:
8 | db_session = SessionLocal()
9 | yield db_session
10 | finally:
11 | await db_session.close()
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/main.py:
--------------------------------------------------------------------------------
1 |
2 | from app import creat_app
3 | app =creat_app()
4 | if __name__ == '__main__':
5 | import uvicorn
6 | uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True)
7 |
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/models/__init__.py
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/models/model.py:
--------------------------------------------------------------------------------
1 | from db.database import Base
2 | from sqlalchemy import Column, String, DateTime, func,Integer#Integer
3 |
4 | class User(Base):
5 | # 指定本类映射到users表
6 | __tablename__ = 'user'
7 | id = Column(Integer, primary_key=True, autoincrement=True)
8 | # 用户号码
9 | phone_number = Column(String(20))
10 | # 用户姓名
11 | username = Column(String(20))
12 | # 用户密码
13 | password = Column(String(32))
14 | # 用户创建时间
15 | created_at = Column(DateTime(), default=func.now())
16 |
17 |
18 |
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 | from pydantic import BaseModel
3 | from starlette.websockets import WebSocket
4 |
5 | @dataclass
6 | class User:
7 | phone_number: str
8 | username: str
9 | websocket:WebSocket
10 |
11 |
12 | class RegisterAaction(BaseModel):
13 | phone_number: str
14 | username: str
15 | password: str
16 |
17 | class LoginAaction(BaseModel):
18 | phone_number: str
19 | password: str
20 |
21 |
22 |
23 | @dataclass
24 | class UserDistribute :
25 | phone_number: str
26 | username: str
27 |
28 | @dataclass
29 | class WebSocketDistribute :
30 | websocket:WebSocket
31 |
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/servies/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/servies/__init__.py
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/distributed_websocket/utils/__init__.py
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/utils/auth_helper.py:
--------------------------------------------------------------------------------
1 |
2 | from fastapi import HTTPException,status
3 | from jose import JWTError, jwt
4 | from pydantic import BaseModel, ValidationError
5 | from jose import jwt
6 |
7 | SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
8 | ALGORITHM = "HS256"
9 |
10 |
11 |
12 | class AuthToeknHelper:
13 |
14 | @staticmethod
15 | def token_encode(data):
16 | jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
17 | return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
18 |
19 | @staticmethod
20 | def token_decode(token):
21 | credentials_exception = HTTPException(
22 | status_code=status.HTTP_401_UNAUTHORIZED,
23 | detail="Could not validate credentials",
24 | headers={"WWW-Authenticate": f"Bearer"},
25 | )
26 | try:
27 | # 开始反向解析我们的TOKEN.,解析相关的信息
28 | payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
29 | except (JWTError, ValidationError):
30 | raise credentials_exception
31 | return payload
32 |
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/utils/passlib_hepler.py:
--------------------------------------------------------------------------------
1 | from passlib.context import CryptContext
2 |
3 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
4 |
5 |
6 | class PasslibHelper:
7 | pass
8 |
9 | # plain_password 明文密码,hashed_password哈希密码
10 | @staticmethod
11 | def verity_password(plain_password: str, hashed_password: str):
12 | """对密码进行校验"""
13 | return pwd_context.verify(plain_password, hashed_password)
14 |
15 | # 进行哈希 密码加密
16 | @staticmethod
17 | def hash_password(password: str) -> str:
18 | return pwd_context.hash(password)
19 |
20 | if __name__ == '__main__':
21 | print(PasslibHelper.hash_password("123456"))
--------------------------------------------------------------------------------
/chapter11/distributed_websocket/utils/random_helper.py:
--------------------------------------------------------------------------------
1 | import string
2 | import random
3 |
4 |
5 |
6 | def generate_short_url(size=7) -> str:
7 | letters = string.ascii_letters + string.digits
8 | short_tag = ''.join(random.choice(letters) for i in range(size))
9 | return short_tag
--------------------------------------------------------------------------------
/chapter11/websocket/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/api/__init__.py
--------------------------------------------------------------------------------
/chapter11/websocket/app.py:
--------------------------------------------------------------------------------
1 | from typing import Any, Dict, List, Optional
2 | from fastapi import Body, FastAPI, HTTPException
3 | from api import room
4 | from api import user
5 |
6 |
7 | app = FastAPI()
8 |
9 |
10 | @app.on_event("startup")
11 | async def startup_event():
12 | pass
13 | from db.database import async_engine, Base
14 | from models.model import User
15 | async def init_create_table():
16 | async with async_engine.begin() as conn:
17 | # await conn.run_sync(Base.metadata.drop_all)
18 | await conn.run_sync(Base.metadata.create_all)
19 |
20 | await init_create_table()
21 | # 实例化房间连接管理类
22 |
23 |
24 | @app.on_event("shutdown")
25 | async def shutdown_event():
26 | pass
27 |
28 |
29 | # 注册路由
30 |
31 | app.include_router(user.router_uesr)
32 | app.include_router(room.router_char)
33 |
34 |
35 | def creat_app():
36 | return app
37 |
--------------------------------------------------------------------------------
/chapter11/websocket/chat.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/chat.db
--------------------------------------------------------------------------------
/chapter11/websocket/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/config/__init__.py
--------------------------------------------------------------------------------
/chapter11/websocket/config/config.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseSettings
2 | from functools import lru_cache
3 |
4 | class Settings(BaseSettings):
5 | # 定义连接异步引擎数据库的URL地址
6 | ASYNC_DATABASE_URI: str = "sqlite+aiosqlite:///chat.db"
7 | # 定义TOEKN的签名信息值
8 | TOKEN_SIGN_SECRET:str = 'ZcjT6Rcp1yIFQoS7'
9 |
10 | @lru_cache()
11 | def get_settings():
12 | return Settings()
13 |
--------------------------------------------------------------------------------
/chapter11/websocket/db/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/db/__init__.py
--------------------------------------------------------------------------------
/chapter11/websocket/db/database.py:
--------------------------------------------------------------------------------
1 | # 导入异步引擎的模块
2 | from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
3 | from sqlalchemy.orm import declarative_base, sessionmaker
4 | # URL地址格式
5 | from config.config import get_settings
6 | # 创建异步引擎对象
7 | async_engine = create_async_engine(get_settings().ASYNC_DATABASE_URI, echo=False)
8 | # 创建ORM模型基类
9 | Base = declarative_base()
10 | # 创建异步的会话管理对象
11 | SessionLocal = sessionmaker(bind=async_engine, expire_on_commit=False, class_=AsyncSession)
--------------------------------------------------------------------------------
/chapter11/websocket/dependencies/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy.ext.asyncio import AsyncSession
2 | from typing import AsyncGenerator
3 | from db.database import SessionLocal
4 |
5 | async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
6 | db_session = None
7 | try:
8 | db_session = SessionLocal()
9 | yield db_session
10 | finally:
11 | await db_session.close()
--------------------------------------------------------------------------------
/chapter11/websocket/main.py:
--------------------------------------------------------------------------------
1 |
2 | from app import creat_app
3 | app =creat_app()
4 | if __name__ == '__main__':
5 | import uvicorn
6 | uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True)
7 |
--------------------------------------------------------------------------------
/chapter11/websocket/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/models/__init__.py
--------------------------------------------------------------------------------
/chapter11/websocket/models/model.py:
--------------------------------------------------------------------------------
1 | from db.database import Base
2 | from sqlalchemy import Column, String, DateTime, func,Integer#Integer
3 |
4 | class User(Base):
5 | # 指定本类映射到users表
6 | __tablename__ = 'user'
7 | id = Column(Integer, primary_key=True, autoincrement=True)
8 | # 用户号码
9 | phone_number = Column(String(20))
10 | # 用户姓名
11 | username = Column(String(20))
12 | # 用户密码
13 | password = Column(String(32))
14 | # 用户创建时间
15 | created_at = Column(DateTime(), default=func.now())
16 |
17 |
18 |
--------------------------------------------------------------------------------
/chapter11/websocket/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 | from pydantic import BaseModel
3 | from starlette.websockets import WebSocket
4 |
5 | @dataclass
6 | class User:
7 | phone_number: str
8 | username: str
9 | websocket:WebSocket
10 |
11 |
12 | class RegisterAaction(BaseModel):
13 | phone_number: str
14 | username: str
15 | password: str
16 |
17 | class LoginAaction(BaseModel):
18 | phone_number: str
19 | password: str
20 |
21 |
22 |
23 | @dataclass
24 | class UserDistribute :
25 | phone_number: str
26 | username: str
27 |
28 | @dataclass
29 | class WebSocketDistribute :
30 | websocket:WebSocket
31 |
--------------------------------------------------------------------------------
/chapter11/websocket/servies/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/servies/__init__.py
--------------------------------------------------------------------------------
/chapter11/websocket/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter11/websocket/utils/__init__.py
--------------------------------------------------------------------------------
/chapter11/websocket/utils/auth_helper.py:
--------------------------------------------------------------------------------
1 |
2 | from fastapi import HTTPException,status
3 | from jose import JWTError, jwt
4 | from pydantic import BaseModel, ValidationError
5 | from jose import jwt
6 |
7 | SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
8 | ALGORITHM = "HS256"
9 |
10 |
11 |
12 | class AuthToeknHelper:
13 |
14 | @staticmethod
15 | def token_encode(data):
16 | jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
17 | return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
18 |
19 | @staticmethod
20 | def token_decode(token):
21 | credentials_exception = HTTPException(
22 | status_code=status.HTTP_401_UNAUTHORIZED,
23 | detail="Could not validate credentials",
24 | headers={"WWW-Authenticate": f"Bearer"},
25 | )
26 | try:
27 | # 开始反向解析我们的TOKEN.,解析相关的信息
28 | payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
29 | except (JWTError, ValidationError):
30 | raise credentials_exception
31 | return payload
32 |
--------------------------------------------------------------------------------
/chapter11/websocket/utils/passlib_hepler.py:
--------------------------------------------------------------------------------
1 | from passlib.context import CryptContext
2 |
3 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
4 |
5 |
6 | class PasslibHelper:
7 | pass
8 |
9 | # plain_password 明文密码,hashed_password哈希密码
10 | @staticmethod
11 | def verity_password(plain_password: str, hashed_password: str):
12 | """对密码进行校验"""
13 | return pwd_context.verify(plain_password, hashed_password)
14 |
15 | # 进行哈希 密码加密
16 | @staticmethod
17 | def hash_password(password: str) -> str:
18 | return pwd_context.hash(password)
19 |
20 | if __name__ == '__main__':
21 | print(PasslibHelper.hash_password("123456"))
--------------------------------------------------------------------------------
/chapter11/websocket/utils/random_helper.py:
--------------------------------------------------------------------------------
1 | import string
2 | import random
3 |
4 |
5 |
6 | def generate_short_url(size=7) -> str:
7 | letters = string.ascii_letters + string.digits
8 | short_tag = ''.join(random.choice(letters) for i in range(size))
9 | return short_tag
--------------------------------------------------------------------------------
/chapter12/booking_system/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/apis/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/doctor/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_docrot = APIRouter(prefix='/api/v1',tags=["医生信息模块"],include_in_schema=True)
3 | from ..api import doctor_api
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/doctor/dependencies/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/apis/doctor/dependencies/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/doctor/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class SchedulingInfo(BaseModel):
5 | # 预约医生编号
6 | dno: str
7 | # 预约时间
8 | start_time: str = None
9 |
10 |
11 | class MakeReserveOrderForm(BaseModel):
12 | # 预约医生编号
13 | dno: str
14 | # 预约医生排号时段
15 | nsindex: str
16 |
17 |
18 | class PayReserveOrderForm(BaseModel):
19 | # 预约医生编号
20 | dno: str
21 | # 预约医生排号时段
22 | nsindex: str
23 | # 预约人信息
24 | visit_uname: str
25 | visit_uphone: str
26 | visit_uopenid: str = None
27 | visit_usex: str
28 | visit_uage: str
29 |
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/hospital/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/apis/hospital/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/hospital/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_hospital = APIRouter(prefix='/api/v1',tags=["医院信息模块"])
3 | # 導入模塊
4 | from apis.hospital.api import get_hospital_info
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/hospital/api/get_hospital_info.py:
--------------------------------------------------------------------------------
1 | from fastapi import Depends
2 | from apis.hospital.repository import HospitalServeries
3 | from db.async_database import depends_get_db_session
4 | from db.async_database import AsyncSession
5 | from exts.responses.json_response import Success
6 | from ..api import router_hospital
7 |
8 |
9 | @router_hospital.get("/hospital_info", summary='获取医院信息')
10 | async def callbadk(db_session: AsyncSession = Depends(depends_get_db_session)):
11 | info = await HospitalServeries.get_hospital_info(db_session, id=1)
12 | return Success(result=info)
13 |
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/hospital/repository/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy import select, update, delete
2 | from sqlalchemy.ext.asyncio import AsyncSession
3 | from db.models import Hospitalinfo
4 | from db.async_database import async_engine, Base
5 |
6 |
7 | class HospitalServeries:
8 |
9 | @staticmethod
10 | async def get_hospital_info(async_session: AsyncSession, id: int):
11 | _result = await async_session.execute(
12 | select(Hospitalinfo.name, Hospitalinfo.describe, Hospitalinfo.describeimages).where(Hospitalinfo.id == id))
13 | scalars_result = _result.first()
14 | # scalars_result = _result.scalars().first()
15 | return scalars_result
16 |
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/payorders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/apis/payorders/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/payorders/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_payorders = APIRouter(prefix='/api/v1',tags=["支付订单模块"])
3 | from apis.payorders.api import doctor_reserve_order
4 | from apis.payorders.api import payback_reserve_order
5 | from apis.payorders.api import reserve_order_info
6 | from apis.payorders.api import doctor_reserve_reorder
7 | from apis.payorders.api import doctor_order_check
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/payorders/dependencies/__init__.py:
--------------------------------------------------------------------------------
1 | from starlette.requests import Request
2 |
3 | def get_client_ip(request: Request):
4 | """
5 | 获取客户端真实ip
6 | :param request:
7 | :return:
8 | """
9 | forwarded = request.headers.get("X-Forwarded-For")
10 | if forwarded:
11 | return forwarded.split(",")[0]
12 | return request.client.host
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/userorders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/apis/userorders/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/userorders/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_userorders = APIRouter(prefix='/api/v1', tags=["用户订单模块"])
3 | from apis.userorders.api import refund_reserve_order, unpay_reserve_order, user_order_info, user_order_list, \
4 | wxauth_login
5 |
--------------------------------------------------------------------------------
/chapter12/booking_system/apis/userorders/api/user_order_list.py:
--------------------------------------------------------------------------------
1 | from fastapi import Depends
2 | from db.async_database import depends_get_db_session
3 | from db.async_database import AsyncSession
4 | from exts.responses.json_response import Success, Fail
5 | from ..api import router_userorders
6 | from ..schemas import UserOrderIonfoListForm
7 | from ..repository import Serveries
8 |
9 | @router_userorders.post("/user_order_list", summary='用户自己订单列表')
10 | async def callbadk(forms: UserOrderIonfoListForm, db_session: AsyncSession = Depends(depends_get_db_session)):
11 | # 检测用户的有消息
12 | # 判断当前用户是否已经被拉黑啦,禁用了!
13 | result = await Serveries.get_order_info_list_by_visit_uopenid_select(db_session,visit_uopenid=forms.visit_uopenid,statue=forms.statue)
14 | # is_reserve -属性 1:表示可以点击预约 2:有排班记录,但是已预约满
15 | return Success(api_code=200, result=result, message='查询成功') if result else Fail(api_code=200, result=None, message='无此订单状态列表信息!')
16 |
--------------------------------------------------------------------------------
/chapter12/booking_system/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/config/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/db/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/db/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/exts/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/requestvar/bing.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
24 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/responses/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | """
4 | -------------------------------------------------
5 | 文件名称 : __init__.py
6 | 文件功能描述 : 功能描述
7 | 创建人 : 小钟同学
8 | 创建时间 : 2021/9/23
9 | -------------------------------------------------
10 | 修改描述-2021/9/23:
11 | -------------------------------------------------
12 | """
13 | from . import json_response
14 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, unicode_literals
2 |
3 | import logging
4 |
5 | from exts.wechatpy.client import WeChatClient # NOQA
6 | from exts.wechatpy.component import ComponentOAuth, WeChatComponent # NOQA
7 | from exts.wechatpy.exceptions import WeChatClientException, WeChatException, WeChatOAuthException, WeChatPayException # NOQA
8 | from exts.wechatpy.oauth import WeChatOAuth # NOQA
9 | from exts.wechatpy.parser import parse_message # NOQA
10 | from exts.wechatpy.pay import WeChatPay # NOQA
11 | from exts.wechatpy.replies import create_reply # NOQA
12 |
13 | __version__ = '1.8.2'
14 | __author__ = 'messense'
15 |
16 | # Set default logging handler to avoid "No handler found" warnings.
17 | try: # Python 2.7+
18 | from logging import NullHandler
19 | except ImportError:
20 | class NullHandler(logging.Handler):
21 | def emit(self, record):
22 | pass
23 |
24 | logging.getLogger(__name__).addHandler(NullHandler())
25 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/_compat.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | wechatpy._compat
4 | ~~~~~~~~~~~~~~~~~
5 |
6 | This module makes it easy for wechatpy to run on both Python 2 and 3.
7 |
8 | :copyright: (c) 2014 by messense.
9 | :license: MIT, see LICENSE for more details.
10 | """
11 | from __future__ import absolute_import, unicode_literals
12 | import sys
13 | import six
14 | import warnings
15 |
16 | warnings.warn("Module `wechatpy._compat` is deprecated, will be removed in 2.0"
17 | "use `wechatpy.utils` instead",
18 | DeprecationWarning, stacklevel=2)
19 |
20 | from exts.wechatpy.utils import get_querystring
21 | from exts.wechatpy.utils import json
22 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/client/api/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class BaseWeChatAPI(object):
6 | """ WeChat API base class """
7 |
8 | def __init__(self, client=None):
9 | self._client = client
10 |
11 | def _get(self, url, **kwargs):
12 | if getattr(self, 'API_BASE_URL', None):
13 | kwargs['api_base_url'] = self.API_BASE_URL
14 | return self._client.get(url, **kwargs)
15 |
16 | def _post(self, url, **kwargs):
17 | if getattr(self, 'API_BASE_URL', None):
18 | kwargs['api_base_url'] = self.API_BASE_URL
19 |
20 | print("当前URL",url)
21 | return self._client.post(url, **kwargs)
22 |
23 | @property
24 | def access_token(self):
25 | return self._client.access_token
26 |
27 | @property
28 | def session(self):
29 | return self._client.session
30 |
31 | @property
32 | def appid(self):
33 | return self._client.appid
34 |
35 | @property
36 | def secret(self):
37 | return self._client.secret
38 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/client/api/merchant/category.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantCategory(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def get_sub_categories(self, cate_id):
11 | res = self._post(
12 | 'merchant/category/getsub',
13 | data={'cate_id': cate_id},
14 | result_processor=lambda x: x['cate_list']
15 | )
16 | return res
17 |
18 | def get_sku_list(self, cate_id):
19 | res = self._post(
20 | 'merchant/category/getsku',
21 | data={'cate_id': cate_id},
22 | result_processor=lambda x: x['sku_table']
23 | )
24 | return res
25 |
26 | def get_properties(self, cate_id):
27 | res = self._post(
28 | 'merchant/category/getproperty',
29 | data={'cate_id': cate_id},
30 | result_processor=lambda x: x['properties']
31 | )
32 | return res
33 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/client/api/merchant/common.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantCommon(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def upload_image(self, filename, image_data):
11 | res = self._post(
12 | 'merchant/common/upload_img',
13 | params={
14 | 'filename': filename
15 | },
16 | data=image_data,
17 | result_processor=lambda x: x['image_url']
18 | )
19 | return res
20 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/client/api/merchant/stock.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantStock(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def add(self, product_id, quantity, sku_info=''):
11 | return self._post(
12 | 'merchant/stock/add',
13 | data={
14 | 'product_id': product_id,
15 | 'quantity': quantity,
16 | 'sku_info': sku_info
17 | }
18 | )
19 |
20 | def reduce(self, product_id, quantity, sku_info=''):
21 | return self._post(
22 | 'merchant/stock/reduce',
23 | data={
24 | 'product_id': product_id,
25 | 'quantity': quantity,
26 | 'sku_info': sku_info
27 | }
28 | )
29 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/crypto/cryptography.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
4 | from cryptography.hazmat.backends import default_backend
5 |
6 |
7 | class WeChatCipher(object):
8 |
9 | def __init__(self, key, iv=None):
10 | iv = iv or key[:16]
11 | backend = default_backend()
12 | self.cipher = Cipher(
13 | algorithms.AES(key),
14 | modes.CBC(iv),
15 | backend=backend
16 | )
17 |
18 | def encrypt(self, plaintext):
19 | encryptor = self.cipher.encryptor()
20 | return encryptor.update(plaintext) + encryptor.finalize()
21 |
22 | def decrypt(self, ciphertext):
23 | decryptor = self.cipher.decryptor()
24 | return decryptor.update(ciphertext) + decryptor.finalize()
25 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/crypto/pkcs7.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.utils import to_binary, byte2int
4 |
5 |
6 | class PKCS7Encoder(object):
7 | block_size = 32
8 |
9 | @classmethod
10 | def encode(cls, text):
11 | length = len(text)
12 | padding_count = cls.block_size - length % cls.block_size
13 | if padding_count == 0:
14 | padding_count = cls.block_size
15 | padding = to_binary(chr(padding_count))
16 | return text + padding * padding_count
17 |
18 | @classmethod
19 | def decode(cls, decrypted):
20 | padding = byte2int(decrypted[-1])
21 | if padding < 1 or padding > 32:
22 | padding = 0
23 | return decrypted[:-padding]
24 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/crypto/pycrypto.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from Crypto.Cipher import AES
4 |
5 |
6 | class WeChatCipher(object):
7 |
8 | def __init__(self, key, iv=None):
9 | iv = iv or key[:16]
10 | self.cipher = AES.new(key, AES.MODE_CBC, iv)
11 |
12 | def encrypt(self, plaintext):
13 | return self.cipher.encrypt(plaintext)
14 |
15 | def decrypt(self, ciphertext):
16 | return self.cipher.decrypt(ciphertext)
17 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/enterprise/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.enterprise.client import WeChatClient # NOQA
5 | from exts.wechatpy.enterprise.crypto import WeChatCrypto # NOQA
6 | from exts.wechatpy.enterprise.parser import parse_message # NOQA
7 | from exts.wechatpy.enterprise.replies import create_reply # NOQA
8 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/enterprise/client/api/misc.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.client.api.base import BaseWeChatAPI
5 |
6 |
7 | class WeChatMisc(BaseWeChatAPI):
8 |
9 | def get_wechat_ips(self):
10 | """
11 | 获取企业微信服务器的ip段
12 |
13 | https://work.weixin.qq.com/api/doc#90000/90135/90238/%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84ip%E6%AE%B5
14 |
15 | :return: 企业微信回调的IP段
16 | """
17 | res = self._get('getcallbackip')
18 | return res['ip_list']
19 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/enterprise/client/api/shakearound.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.client.api.base import BaseWeChatAPI
5 |
6 |
7 | class WeChatShakeAround(BaseWeChatAPI):
8 |
9 | def get_shake_info(self, ticket):
10 | """
11 | 获取摇周边的设备及用户信息
12 |
13 | https://qydev.weixin.qq.com/wiki/index.php?title=获取设备及用户信息
14 |
15 | :param ticket: 摇周边业务的ticket,可在摇到的 URL 中得到,ticket 生效时间为30分钟
16 | :return: 设备及用户信息
17 | """
18 | res = self._post(
19 | 'shakearound/getshakeinfo',
20 | data={
21 | 'ticket': ticket
22 | }
23 | )
24 | return res['data']
25 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/enterprise/exceptions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.exceptions import WeChatException
5 |
6 |
7 | class InvalidCorpIdException(WeChatException):
8 |
9 | def __init__(self, errcode=-40005, errmsg='Invalid corp_id'):
10 | super(InvalidCorpIdException, self).__init__(errcode, errmsg)
11 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/enterprise/parser.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | import xmltodict
5 |
6 | from exts.wechatpy.enterprise.events import EVENT_TYPES
7 | from exts.wechatpy.enterprise.messages import MESSAGE_TYPES
8 | from exts.wechatpy.messages import UnknownMessage
9 | from exts.wechatpy.utils import to_text
10 |
11 |
12 | def parse_message(xml):
13 | if not xml:
14 | return
15 | message = xmltodict.parse(to_text(xml))['xml']
16 | message_type = message['MsgType'].lower()
17 | if message_type == 'event':
18 | event_type = message['Event'].lower()
19 | message_class = EVENT_TYPES.get(event_type, UnknownMessage)
20 | else:
21 | message_class = MESSAGE_TYPES.get(message_type, UnknownMessage)
22 | return message_class(message)
23 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/pay/api/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.pay.api.redpack import WeChatRedpack # NOQA
4 | from exts.wechatpy.pay.api.transfer import WeChatTransfer # NOQA
5 | from exts.wechatpy.pay.api.coupon import WeChatCoupon # NOQA
6 | from exts.wechatpy.pay.api.order import WeChatOrder # NOQA
7 | from exts.wechatpy.pay.api.refund import WeChatRefund # NOQA
8 | from exts.wechatpy.pay.api.tools import WeChatTools # NOQA
9 | from exts.wechatpy.pay.api.jsapi import WeChatJSAPI # NOQA
10 | from exts.wechatpy.pay.api.micropay import WeChatMicroPay # NOQA
11 | from exts.wechatpy.pay.api.withhold import WeChatWithhold # NOQA
12 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/pay/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class BaseWeChatPayAPI(object):
6 | """ WeChat Pay API base class """
7 | def __init__(self, client=None):
8 | self._client = client
9 |
10 | def _get(self, url, **kwargs):
11 | if getattr(self, 'API_BASE_URL', None):
12 | kwargs['api_base_url'] = self.API_BASE_URL
13 | return self._client.get(url, **kwargs)
14 |
15 | def _post(self, url, **kwargs):
16 | if getattr(self, 'API_BASE_URL', None):
17 | kwargs['api_base_url'] = self.API_BASE_URL
18 | return self._client.post(url, **kwargs)
19 |
20 | @property
21 | def appid(self):
22 | return self._client.appid
23 |
24 | @property
25 | def sub_appid(self):
26 | return self._client.sub_appid
27 |
28 | @property
29 | def mch_id(self):
30 | return self._client.mch_id
31 |
32 | @property
33 | def sub_mch_id(self):
34 | return self._client.sub_mch_id
35 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/session/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class SessionStorage(object):
6 |
7 | def get(self, key, default=None):
8 | raise NotImplementedError()
9 |
10 | def set(self, key, value, ttl=None):
11 | raise NotImplementedError()
12 |
13 | def delete(self, key):
14 | raise NotImplementedError()
15 |
16 | def __getitem__(self, key):
17 | self.get(key)
18 |
19 | def __setitem__(self, key, value):
20 | self.set(key, value)
21 |
22 | def __delitem__(self, key):
23 | self.delete(key)
24 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/session/memorystorage.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.session import SessionStorage
4 |
5 |
6 | class MemoryStorage(SessionStorage):
7 |
8 | def __init__(self):
9 | self._data = {}
10 |
11 | def get(self, key, default=None):
12 | return self._data.get(key, default)
13 |
14 | def set(self, key, value, ttl=None):
15 | if value is None:
16 | return
17 | self._data[key] = value
18 |
19 | def delete(self, key):
20 | self._data.pop(key, None)
21 |
--------------------------------------------------------------------------------
/chapter12/booking_system/exts/wechatpy/session/shovestorage.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.session import SessionStorage
4 |
5 |
6 | class ShoveStorage(SessionStorage):
7 |
8 | def __init__(self, shove, prefix='wechatpy'):
9 | self.shove = shove
10 | self.prefix = prefix
11 |
12 | def key_name(self, key):
13 | return '{0}:{1}'.format(self.prefix, key)
14 |
15 | def get(self, key, default=None):
16 | key = self.key_name(key)
17 | try:
18 | return self.shove[key]
19 | except KeyError:
20 | return default
21 |
22 | def set(self, key, value, ttl=None):
23 | if value is None:
24 | return
25 |
26 | key = self.key_name(key)
27 | self.shove[key] = value
28 |
29 | def delete(self, key):
30 | key = self.key_name(key)
31 | try:
32 | del self.shove[key]
33 | except KeyError:
34 | pass
35 |
--------------------------------------------------------------------------------
/chapter12/booking_system/main.py:
--------------------------------------------------------------------------------
1 | from app import creat_app
2 | app =creat_app()
3 | if __name__ == "__main__":
4 | import uvicorn
5 | import os
6 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
7 | print(app_modeel_name)
8 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
9 |
10 |
11 | # tree -I "node_modules|cache|test_*"
12 | # tree -I "__pycache__"
--------------------------------------------------------------------------------
/chapter12/booking_system/middlewares/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/middlewares/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/middlewares/loger/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/middlewares/loger/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/middlewares/loger/bing.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
24 |
--------------------------------------------------------------------------------
/chapter12/booking_system/plugins/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/plugins/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/plugins/base.py:
--------------------------------------------------------------------------------
1 | import fastapi
2 | import pydantic
3 | import typing
4 | import abc
5 |
6 | class PluginBase(abc.ABC):
7 |
8 | def __init__(self,app: fastapi.FastAPI = None,config: pydantic.BaseSettings = None):
9 | if app is not None:
10 | self.init_app(app)
11 |
12 | @abc.abstractmethod
13 | def init_app(self,app: fastapi.FastAPI,config: pydantic.BaseSettings = None,*args,**kwargs) -> None:
14 | raise NotImplementedError('需要实现初始化')
15 |
--------------------------------------------------------------------------------
/chapter12/booking_system/requirements.txt:
--------------------------------------------------------------------------------
1 | aio-pika==8.0.3
2 | aiormq==6.3.4
3 | anyio==3.6.1
4 | asgiref==3.5.2
5 | asyncpg==0.26.0
6 | certifi==2022.6.15
7 | charset-normalizer==2.1.0
8 | click==8.1.3
9 | colorama==0.4.5
10 | dnspython==2.2.1
11 | email-validator==1.2.1
12 | fastapi==0.79.0
13 | greenlet==1.1.2
14 | gunicorn==20.1.0
15 | h11==0.13.0
16 | httptools==0.4.0
17 | idna==3.3
18 | itsdangerous==2.1.2
19 | Jinja2==3.1.2
20 | MarkupSafe==2.1.1
21 | multidict==6.0.2
22 | optionaldict==0.1.2
23 | orjson==3.7.8
24 | pamqp==3.2.0
25 | pika==1.3.0
26 | psycopg2==2.9.3
27 | pycryptodome==3.15.0
28 | pydantic==1.9.1
29 | python-dotenv==0.20.0
30 | python-multipart==0.0.5
31 | PyYAML==6.0
32 | requests==2.28.1
33 | six==1.16.0
34 | sniffio==1.2.0
35 | SQLAlchemy==1.4.39
36 | starlette==0.19.1
37 | typing_extensions==4.3.0
38 | ujson==5.4.0
39 | urllib3==1.26.10
40 | uvicorn==0.17.6
41 | watchgod==0.8.2
42 | websockets==10.3
43 | xmltodict==0.13.0
44 | yarl==1.7.2
45 |
--------------------------------------------------------------------------------
/chapter12/booking_system/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/utils/__init__.py
--------------------------------------------------------------------------------
/chapter12/booking_system/utils/cast_helper.py:
--------------------------------------------------------------------------------
1 | def add(a,b):
2 | return a+b;
--------------------------------------------------------------------------------
/chapter12/booking_system/utils/run_with_asyncio.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 | import asyncio
3 | from functools import wraps
4 | from typing import Any, Awaitable, Callable, TypeVar
5 | T = TypeVar("T")
6 | __all__ = ["run_with_asyncio"]
7 | def run_with_asyncio(f: Callable[..., Awaitable[T]]) -> Callable[..., T]:
8 | @wraps(f)
9 | def wrapper(*args: Any, **kwargs: Any) -> T:
10 | print("pajinlail")
11 | return asyncio.run(f(*args, **kwargs))
12 | return wrapper
--------------------------------------------------------------------------------
/chapter12/booking_system/wxchatsdk/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter12/booking_system/wxchatsdk/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/apis/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/doctor/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_docrot = APIRouter(prefix='/api/v1',tags=["医生信息模块"],include_in_schema=True)
3 | from ..api import doctor_api
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/doctor/dependencies/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/apis/doctor/dependencies/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/doctor/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class SchedulingInfo(BaseModel):
5 | # 预约医生编号
6 | dno: str
7 | # 预约时间
8 | start_time: str = None
9 |
10 |
11 | class MakeReserveOrderForm(BaseModel):
12 | # 预约医生编号
13 | dno: str
14 | # 预约医生排号时段
15 | nsindex: str
16 |
17 |
18 | class PayReserveOrderForm(BaseModel):
19 | # 预约医生编号
20 | dno: str
21 | # 预约医生排号时段
22 | nsindex: str
23 | # 预约人信息
24 | visit_uname: str
25 | visit_uphone: str
26 | visit_uopenid: str = None
27 | visit_usex: str
28 | visit_uage: str
29 |
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/hospital/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/apis/hospital/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/hospital/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_hospital = APIRouter(prefix='/api/v1',tags=["医院信息模块"])
3 | # 導入模塊
4 | from apis.hospital.api import get_hospital_info
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/hospital/api/get_hospital_info.py:
--------------------------------------------------------------------------------
1 | from fastapi import Depends
2 | from apis.hospital.repository import HospitalServeries
3 | from db.async_database import depends_get_db_session
4 | from db.async_database import AsyncSession
5 | from exts.responses.json_response import Success
6 | from ..api import router_hospital
7 |
8 |
9 | @router_hospital.get("/hospital_info", summary='获取医院信息')
10 | async def callbadk(db_session: AsyncSession = Depends(depends_get_db_session)):
11 | info = await HospitalServeries.get_hospital_info(db_session, id=1)
12 | return Success(result=info)
13 |
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/hospital/repository/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy import select, update, delete
2 | from sqlalchemy.ext.asyncio import AsyncSession
3 | from db.models import Hospitalinfo
4 | from db.async_database import async_engine, Base
5 |
6 |
7 | class HospitalServeries:
8 |
9 | @staticmethod
10 | async def get_hospital_info(async_session: AsyncSession, id: int):
11 | _result = await async_session.execute(
12 | select(Hospitalinfo.name, Hospitalinfo.describe, Hospitalinfo.describeimages).where(Hospitalinfo.id == id))
13 | scalars_result = _result.first()
14 | # scalars_result = _result.scalars().first()
15 | return scalars_result
16 |
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/payorders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/apis/payorders/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/payorders/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_payorders = APIRouter(prefix='/api/v1',tags=["支付订单模块"])
3 | from apis.payorders.api import doctor_reserve_order
4 | from apis.payorders.api import payback_reserve_order
5 | from apis.payorders.api import reserve_order_info
6 | from apis.payorders.api import doctor_reserve_reorder
7 | from apis.payorders.api import doctor_order_check
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/payorders/dependencies/__init__.py:
--------------------------------------------------------------------------------
1 | from starlette.requests import Request
2 |
3 | def get_client_ip(request: Request):
4 | """
5 | 获取客户端真实ip
6 | :param request:
7 | :return:
8 | """
9 | forwarded = request.headers.get("X-Forwarded-For")
10 | if forwarded:
11 | return forwarded.split(",")[0]
12 | return request.client.host
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/userorders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/apis/userorders/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/userorders/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_userorders = APIRouter(prefix='/api/v1', tags=["用户订单模块"])
3 | from apis.userorders.api import refund_reserve_order, unpay_reserve_order, user_order_info, user_order_list, \
4 | wxauth_login
5 |
--------------------------------------------------------------------------------
/chapter13/booking_system/apis/userorders/api/user_order_list.py:
--------------------------------------------------------------------------------
1 | from fastapi import Depends
2 | from db.async_database import depends_get_db_session
3 | from db.async_database import AsyncSession
4 | from exts.responses.json_response import Success, Fail
5 | from ..api import router_userorders
6 | from ..schemas import UserOrderIonfoListForm
7 | from ..repository import Serveries
8 |
9 | @router_userorders.post("/user_order_list", summary='用户自己订单列表')
10 | async def callbadk(forms: UserOrderIonfoListForm, db_session: AsyncSession = Depends(depends_get_db_session)):
11 | # 检测用户的有消息
12 | # 判断当前用户是否已经被拉黑啦,禁用了!
13 | result = await Serveries.get_order_info_list_by_visit_uopenid_select(db_session,visit_uopenid=forms.visit_uopenid,statue=forms.statue)
14 | # is_reserve -属性 1:表示可以点击预约 2:有排班记录,但是已预约满
15 | return Success(api_code=200, result=result, message='查询成功') if result else Fail(api_code=200, result=None, message='无此订单状态列表信息!')
16 |
--------------------------------------------------------------------------------
/chapter13/booking_system/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/config/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/db/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/db/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/exts/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/requestvar/bing.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
24 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/responses/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | """
4 | -------------------------------------------------
5 | 文件名称 : __init__.py
6 | 文件功能描述 : 功能描述
7 | 创建人 : 小钟同学
8 | 创建时间 : 2021/9/23
9 | -------------------------------------------------
10 | 修改描述-2021/9/23:
11 | -------------------------------------------------
12 | """
13 | from . import json_response
14 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, unicode_literals
2 |
3 | import logging
4 |
5 | from exts.wechatpy.client import WeChatClient # NOQA
6 | from exts.wechatpy.component import ComponentOAuth, WeChatComponent # NOQA
7 | from exts.wechatpy.exceptions import WeChatClientException, WeChatException, WeChatOAuthException, WeChatPayException # NOQA
8 | from exts.wechatpy.oauth import WeChatOAuth # NOQA
9 | from exts.wechatpy.parser import parse_message # NOQA
10 | from exts.wechatpy.pay import WeChatPay # NOQA
11 | from exts.wechatpy.replies import create_reply # NOQA
12 |
13 | __version__ = '1.8.2'
14 | __author__ = 'messense'
15 |
16 | # Set default logging handler to avoid "No handler found" warnings.
17 | try: # Python 2.7+
18 | from logging import NullHandler
19 | except ImportError:
20 | class NullHandler(logging.Handler):
21 | def emit(self, record):
22 | pass
23 |
24 | logging.getLogger(__name__).addHandler(NullHandler())
25 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/_compat.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | wechatpy._compat
4 | ~~~~~~~~~~~~~~~~~
5 |
6 | This module makes it easy for wechatpy to run on both Python 2 and 3.
7 |
8 | :copyright: (c) 2014 by messense.
9 | :license: MIT, see LICENSE for more details.
10 | """
11 | from __future__ import absolute_import, unicode_literals
12 | import sys
13 | import six
14 | import warnings
15 |
16 | warnings.warn("Module `wechatpy._compat` is deprecated, will be removed in 2.0"
17 | "use `wechatpy.utils` instead",
18 | DeprecationWarning, stacklevel=2)
19 |
20 | from exts.wechatpy.utils import get_querystring
21 | from exts.wechatpy.utils import json
22 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/client/api/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class BaseWeChatAPI(object):
6 | """ WeChat API base class """
7 |
8 | def __init__(self, client=None):
9 | self._client = client
10 |
11 | def _get(self, url, **kwargs):
12 | if getattr(self, 'API_BASE_URL', None):
13 | kwargs['api_base_url'] = self.API_BASE_URL
14 | return self._client.get(url, **kwargs)
15 |
16 | def _post(self, url, **kwargs):
17 | if getattr(self, 'API_BASE_URL', None):
18 | kwargs['api_base_url'] = self.API_BASE_URL
19 |
20 | print("当前URL",url)
21 | return self._client.post(url, **kwargs)
22 |
23 | @property
24 | def access_token(self):
25 | return self._client.access_token
26 |
27 | @property
28 | def session(self):
29 | return self._client.session
30 |
31 | @property
32 | def appid(self):
33 | return self._client.appid
34 |
35 | @property
36 | def secret(self):
37 | return self._client.secret
38 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/client/api/merchant/category.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantCategory(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def get_sub_categories(self, cate_id):
11 | res = self._post(
12 | 'merchant/category/getsub',
13 | data={'cate_id': cate_id},
14 | result_processor=lambda x: x['cate_list']
15 | )
16 | return res
17 |
18 | def get_sku_list(self, cate_id):
19 | res = self._post(
20 | 'merchant/category/getsku',
21 | data={'cate_id': cate_id},
22 | result_processor=lambda x: x['sku_table']
23 | )
24 | return res
25 |
26 | def get_properties(self, cate_id):
27 | res = self._post(
28 | 'merchant/category/getproperty',
29 | data={'cate_id': cate_id},
30 | result_processor=lambda x: x['properties']
31 | )
32 | return res
33 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/client/api/merchant/common.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantCommon(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def upload_image(self, filename, image_data):
11 | res = self._post(
12 | 'merchant/common/upload_img',
13 | params={
14 | 'filename': filename
15 | },
16 | data=image_data,
17 | result_processor=lambda x: x['image_url']
18 | )
19 | return res
20 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/client/api/merchant/stock.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantStock(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def add(self, product_id, quantity, sku_info=''):
11 | return self._post(
12 | 'merchant/stock/add',
13 | data={
14 | 'product_id': product_id,
15 | 'quantity': quantity,
16 | 'sku_info': sku_info
17 | }
18 | )
19 |
20 | def reduce(self, product_id, quantity, sku_info=''):
21 | return self._post(
22 | 'merchant/stock/reduce',
23 | data={
24 | 'product_id': product_id,
25 | 'quantity': quantity,
26 | 'sku_info': sku_info
27 | }
28 | )
29 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/crypto/cryptography.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
4 | from cryptography.hazmat.backends import default_backend
5 |
6 |
7 | class WeChatCipher(object):
8 |
9 | def __init__(self, key, iv=None):
10 | iv = iv or key[:16]
11 | backend = default_backend()
12 | self.cipher = Cipher(
13 | algorithms.AES(key),
14 | modes.CBC(iv),
15 | backend=backend
16 | )
17 |
18 | def encrypt(self, plaintext):
19 | encryptor = self.cipher.encryptor()
20 | return encryptor.update(plaintext) + encryptor.finalize()
21 |
22 | def decrypt(self, ciphertext):
23 | decryptor = self.cipher.decryptor()
24 | return decryptor.update(ciphertext) + decryptor.finalize()
25 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/crypto/pkcs7.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.utils import to_binary, byte2int
4 |
5 |
6 | class PKCS7Encoder(object):
7 | block_size = 32
8 |
9 | @classmethod
10 | def encode(cls, text):
11 | length = len(text)
12 | padding_count = cls.block_size - length % cls.block_size
13 | if padding_count == 0:
14 | padding_count = cls.block_size
15 | padding = to_binary(chr(padding_count))
16 | return text + padding * padding_count
17 |
18 | @classmethod
19 | def decode(cls, decrypted):
20 | padding = byte2int(decrypted[-1])
21 | if padding < 1 or padding > 32:
22 | padding = 0
23 | return decrypted[:-padding]
24 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/crypto/pycrypto.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from Crypto.Cipher import AES
4 |
5 |
6 | class WeChatCipher(object):
7 |
8 | def __init__(self, key, iv=None):
9 | iv = iv or key[:16]
10 | self.cipher = AES.new(key, AES.MODE_CBC, iv)
11 |
12 | def encrypt(self, plaintext):
13 | return self.cipher.encrypt(plaintext)
14 |
15 | def decrypt(self, ciphertext):
16 | return self.cipher.decrypt(ciphertext)
17 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/enterprise/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.enterprise.client import WeChatClient # NOQA
5 | from exts.wechatpy.enterprise.crypto import WeChatCrypto # NOQA
6 | from exts.wechatpy.enterprise.parser import parse_message # NOQA
7 | from exts.wechatpy.enterprise.replies import create_reply # NOQA
8 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/enterprise/client/api/misc.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.client.api.base import BaseWeChatAPI
5 |
6 |
7 | class WeChatMisc(BaseWeChatAPI):
8 |
9 | def get_wechat_ips(self):
10 | """
11 | 获取企业微信服务器的ip段
12 |
13 | https://work.weixin.qq.com/api/doc#90000/90135/90238/%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84ip%E6%AE%B5
14 |
15 | :return: 企业微信回调的IP段
16 | """
17 | res = self._get('getcallbackip')
18 | return res['ip_list']
19 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/enterprise/client/api/shakearound.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.client.api.base import BaseWeChatAPI
5 |
6 |
7 | class WeChatShakeAround(BaseWeChatAPI):
8 |
9 | def get_shake_info(self, ticket):
10 | """
11 | 获取摇周边的设备及用户信息
12 |
13 | https://qydev.weixin.qq.com/wiki/index.php?title=获取设备及用户信息
14 |
15 | :param ticket: 摇周边业务的ticket,可在摇到的 URL 中得到,ticket 生效时间为30分钟
16 | :return: 设备及用户信息
17 | """
18 | res = self._post(
19 | 'shakearound/getshakeinfo',
20 | data={
21 | 'ticket': ticket
22 | }
23 | )
24 | return res['data']
25 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/enterprise/exceptions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.exceptions import WeChatException
5 |
6 |
7 | class InvalidCorpIdException(WeChatException):
8 |
9 | def __init__(self, errcode=-40005, errmsg='Invalid corp_id'):
10 | super(InvalidCorpIdException, self).__init__(errcode, errmsg)
11 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/enterprise/parser.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | import xmltodict
5 |
6 | from exts.wechatpy.enterprise.events import EVENT_TYPES
7 | from exts.wechatpy.enterprise.messages import MESSAGE_TYPES
8 | from exts.wechatpy.messages import UnknownMessage
9 | from exts.wechatpy.utils import to_text
10 |
11 |
12 | def parse_message(xml):
13 | if not xml:
14 | return
15 | message = xmltodict.parse(to_text(xml))['xml']
16 | message_type = message['MsgType'].lower()
17 | if message_type == 'event':
18 | event_type = message['Event'].lower()
19 | message_class = EVENT_TYPES.get(event_type, UnknownMessage)
20 | else:
21 | message_class = MESSAGE_TYPES.get(message_type, UnknownMessage)
22 | return message_class(message)
23 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/pay/api/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.pay.api.redpack import WeChatRedpack # NOQA
4 | from exts.wechatpy.pay.api.transfer import WeChatTransfer # NOQA
5 | from exts.wechatpy.pay.api.coupon import WeChatCoupon # NOQA
6 | from exts.wechatpy.pay.api.order import WeChatOrder # NOQA
7 | from exts.wechatpy.pay.api.refund import WeChatRefund # NOQA
8 | from exts.wechatpy.pay.api.tools import WeChatTools # NOQA
9 | from exts.wechatpy.pay.api.jsapi import WeChatJSAPI # NOQA
10 | from exts.wechatpy.pay.api.micropay import WeChatMicroPay # NOQA
11 | from exts.wechatpy.pay.api.withhold import WeChatWithhold # NOQA
12 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/pay/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class BaseWeChatPayAPI(object):
6 | """ WeChat Pay API base class """
7 | def __init__(self, client=None):
8 | self._client = client
9 |
10 | def _get(self, url, **kwargs):
11 | if getattr(self, 'API_BASE_URL', None):
12 | kwargs['api_base_url'] = self.API_BASE_URL
13 | return self._client.get(url, **kwargs)
14 |
15 | def _post(self, url, **kwargs):
16 | if getattr(self, 'API_BASE_URL', None):
17 | kwargs['api_base_url'] = self.API_BASE_URL
18 | return self._client.post(url, **kwargs)
19 |
20 | @property
21 | def appid(self):
22 | return self._client.appid
23 |
24 | @property
25 | def sub_appid(self):
26 | return self._client.sub_appid
27 |
28 | @property
29 | def mch_id(self):
30 | return self._client.mch_id
31 |
32 | @property
33 | def sub_mch_id(self):
34 | return self._client.sub_mch_id
35 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/session/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class SessionStorage(object):
6 |
7 | def get(self, key, default=None):
8 | raise NotImplementedError()
9 |
10 | def set(self, key, value, ttl=None):
11 | raise NotImplementedError()
12 |
13 | def delete(self, key):
14 | raise NotImplementedError()
15 |
16 | def __getitem__(self, key):
17 | self.get(key)
18 |
19 | def __setitem__(self, key, value):
20 | self.set(key, value)
21 |
22 | def __delitem__(self, key):
23 | self.delete(key)
24 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/session/memorystorage.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.session import SessionStorage
4 |
5 |
6 | class MemoryStorage(SessionStorage):
7 |
8 | def __init__(self):
9 | self._data = {}
10 |
11 | def get(self, key, default=None):
12 | return self._data.get(key, default)
13 |
14 | def set(self, key, value, ttl=None):
15 | if value is None:
16 | return
17 | self._data[key] = value
18 |
19 | def delete(self, key):
20 | self._data.pop(key, None)
21 |
--------------------------------------------------------------------------------
/chapter13/booking_system/exts/wechatpy/session/shovestorage.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.session import SessionStorage
4 |
5 |
6 | class ShoveStorage(SessionStorage):
7 |
8 | def __init__(self, shove, prefix='wechatpy'):
9 | self.shove = shove
10 | self.prefix = prefix
11 |
12 | def key_name(self, key):
13 | return '{0}:{1}'.format(self.prefix, key)
14 |
15 | def get(self, key, default=None):
16 | key = self.key_name(key)
17 | try:
18 | return self.shove[key]
19 | except KeyError:
20 | return default
21 |
22 | def set(self, key, value, ttl=None):
23 | if value is None:
24 | return
25 |
26 | key = self.key_name(key)
27 | self.shove[key] = value
28 |
29 | def delete(self, key):
30 | key = self.key_name(key)
31 | try:
32 | del self.shove[key]
33 | except KeyError:
34 | pass
35 |
--------------------------------------------------------------------------------
/chapter13/booking_system/main.py:
--------------------------------------------------------------------------------
1 | from app import creat_app
2 | app =creat_app()
3 | if __name__ == "__main__":
4 | import uvicorn
5 | import os
6 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
7 | print(app_modeel_name)
8 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
9 |
10 |
11 | # tree -I "node_modules|cache|test_*"
12 | # tree -I "__pycache__"
--------------------------------------------------------------------------------
/chapter13/booking_system/middlewares/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/middlewares/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/middlewares/loger/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/middlewares/loger/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/middlewares/loger/bing.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
24 |
--------------------------------------------------------------------------------
/chapter13/booking_system/plugins/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/plugins/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/plugins/base.py:
--------------------------------------------------------------------------------
1 | import fastapi
2 | import pydantic
3 | import typing
4 | import abc
5 |
6 | class PluginBase(abc.ABC):
7 |
8 | def __init__(self,app: fastapi.FastAPI = None,config: pydantic.BaseSettings = None):
9 | if app is not None:
10 | self.init_app(app)
11 |
12 | @abc.abstractmethod
13 | def init_app(self,app: fastapi.FastAPI,config: pydantic.BaseSettings = None,*args,**kwargs) -> None:
14 | raise NotImplementedError('需要实现初始化')
15 |
--------------------------------------------------------------------------------
/chapter13/booking_system/requirements.txt:
--------------------------------------------------------------------------------
1 | aio-pika==8.0.3
2 | aiormq==6.3.4
3 | anyio==3.6.1
4 | asgiref==3.5.2
5 | asyncpg==0.26.0
6 | certifi==2022.6.15
7 | charset-normalizer==2.1.0
8 | click==8.1.3
9 | colorama==0.4.5
10 | dnspython==2.2.1
11 | email-validator==1.2.1
12 | fastapi==0.79.0
13 | greenlet==1.1.2
14 | gunicorn==20.1.0
15 | h11==0.13.0
16 | httptools==0.4.0
17 | idna==3.3
18 | itsdangerous==2.1.2
19 | Jinja2==3.1.2
20 | MarkupSafe==2.1.1
21 | multidict==6.0.2
22 | optionaldict==0.1.2
23 | orjson==3.7.8
24 | pamqp==3.2.0
25 | pika==1.3.0
26 | psycopg2==2.9.3
27 | pycryptodome==3.15.0
28 | pydantic==1.9.1
29 | python-dotenv==0.20.0
30 | python-multipart==0.0.5
31 | PyYAML==6.0
32 | requests==2.28.1
33 | six==1.16.0
34 | sniffio==1.2.0
35 | SQLAlchemy==1.4.39
36 | starlette==0.19.1
37 | typing_extensions==4.3.0
38 | ujson==5.4.0
39 | urllib3==1.26.10
40 | uvicorn==0.17.6
41 | watchgod==0.8.2
42 | websockets==10.3
43 | xmltodict==0.13.0
44 | yarl==1.7.2
45 |
--------------------------------------------------------------------------------
/chapter13/booking_system/testcase/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/testcase/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/testcase/test_async_api_v2.py:
--------------------------------------------------------------------------------
1 | # from uuid import UUID
2 | #
3 | import pytest
4 | from httpx import AsyncClient
5 | pytestmark = pytest.mark.anyio
6 |
7 | async def test_hospital_info(async_client: AsyncClient):
8 | response = await async_client.get("/api/v1/hospital_info")
9 | print('response', response.text)
10 | assert response.status_code == 200
11 |
12 |
13 | async def test_doctor_list(async_client: AsyncClient):
14 | response = await async_client.get("/api/v1/doctor_list")
15 | print('response', response.text)
16 | assert response.status_code == 200
--------------------------------------------------------------------------------
/chapter13/booking_system/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/utils/__init__.py
--------------------------------------------------------------------------------
/chapter13/booking_system/utils/cast_helper.py:
--------------------------------------------------------------------------------
1 | def add(a,b):
2 | return a+b;
--------------------------------------------------------------------------------
/chapter13/booking_system/utils/run_with_asyncio.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 | import asyncio
3 | from functools import wraps
4 | from typing import Any, Awaitable, Callable, TypeVar
5 | T = TypeVar("T")
6 | __all__ = ["run_with_asyncio"]
7 | def run_with_asyncio(f: Callable[..., Awaitable[T]]) -> Callable[..., T]:
8 | @wraps(f)
9 | def wrapper(*args: Any, **kwargs: Any) -> T:
10 | print("pajinlail")
11 | return asyncio.run(f(*args, **kwargs))
12 | return wrapper
--------------------------------------------------------------------------------
/chapter13/booking_system/wxchatsdk/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/booking_system/wxchatsdk/__init__.py
--------------------------------------------------------------------------------
/chapter13/pytest_demo/cast_helper.py:
--------------------------------------------------------------------------------
1 | def add(a,b):
2 | return a+b;
--------------------------------------------------------------------------------
/chapter13/pytest_demo/test_add.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from cast_helper import add
3 |
4 |
5 | class TestMyAddClass:
6 |
7 |
8 | def setup(self):
9 | print("setup前置条件")
10 |
11 | def teardown(self):
12 | print("teardown后置条件")
13 |
14 | def setup_class(self):
15 | print("前置条件")
16 |
17 | def teardown_class(self):
18 | print("后置条件")
19 |
20 | def test_add(self):
21 | assert 3 == 3
22 |
23 | def test_add_v2(self):
24 | assert 3 == 5
25 |
26 | if __name__ == "__main__":
27 | pytest.main(['-q'])
28 |
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/testcase/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | @pytest.fixture(scope="session", autouse=True)
5 | def action_01():
6 | print("session-类型作用域-前置条件")
7 | yield
8 | print("session-类型作用域-后置条件")
9 |
10 |
11 | @pytest.fixture(scope="module", autouse=True)
12 | def action_02():
13 | print("module-类型作用域-前置条件")
14 | yield
15 | print("module-类型作用域-后置条件")
16 |
17 |
18 | # 生效的范围,类级别,每个类才会执行一次
19 | @pytest.fixture(scope="class", autouse=True)
20 | def action_03():
21 | print("class-类型作用域-前置条件")
22 | yield
23 | print("class-类型作用域-后置条件")
24 |
25 |
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/testcase/test_case1.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | def test_get_user_role(action_01):
4 | print(f"获取当前用户角色:{action_01}")
5 |
6 | if __name__ == "__main__":
7 | pytest.main()
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter13/pytest_fixture_demo/tests/__init__.py
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/tests/test_fixs.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | def setup():
5 | print('setup 用例开始前执行')
6 |
7 | def teardown():
8 | print('teardown 用例结束后执行')
9 |
10 | # 定义一个前后置方法
11 | @pytest.fixture
12 | def my_first_fixture():
13 | print("前置方法")
14 | yield
15 | print("后置方法")
16 |
17 |
18 | # 定义测试用例
19 | def test_cast_1(my_first_fixture):
20 | print("开始执行cast_1测试用例")
21 | assert 3 == 3
22 |
23 |
24 | # 定义测试用例
25 | def test_cast_2(my_first_fixture):
26 | print("开始执行cast_2测试用例")
27 | assert 3 == 3
28 |
29 |
30 | if __name__ == "__main__":
31 | pytest.main()
32 |
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/tests/test_fixs_parametrize.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | # 字典列表
4 | data = ["superadmin", "admin", "common"]
5 | data2 = ["superadmin2", "admin2", "common2"]
6 |
7 | @pytest.mark.parametrize("request_data", data)
8 | def test_get_user_role(request_data):
9 | print(f"获取当前用户角色:{request_data}")
10 |
11 | @pytest.mark.parametrize("data",data)
12 | @pytest.mark.parametrize("data2",data2)
13 | def test_a(data,data2):
14 | print(f"测试参数组合,data:{data},data2:{data}")
15 |
16 |
17 | if __name__ == "__main__":
18 | pytest.main()
19 |
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/tests/test_fixs_parametrize_class.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | @pytest.mark.parametrize("role_name,age", [("superadmin",45), ("admin",4), ("common",6)])
5 | class TestGetUserRole:
6 | def test_get_user_role(self,role_name,age):
7 | print(f"获取当前用户角色:{role_name,age}")
8 |
9 | if __name__ == "__main__":
10 | pytest.main()
--------------------------------------------------------------------------------
/chapter13/pytest_fixture_demo/tests/test_fixs_params.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | data = ["superadmin", "admin","common"]
4 |
5 | @pytest.fixture(scope="function",name='user_role_fixture', params=data,autouse=True)
6 | def user_role(request):
7 | print("当前用例使用的参数:",request.param)
8 | return request.param
9 |
10 | def test_get_user_role(user_role_fixture):
11 | print(f"获取当前用户角色:{user_role_fixture}")
12 |
13 |
14 | if __name__ == "__main__":
15 | pytest.main()
--------------------------------------------------------------------------------
/chapter13/unittest_demo/main.py:
--------------------------------------------------------------------------------
1 | # unittest导入
2 | import unittest
3 |
4 | # 定义测试类
5 | class UnitTestForAdd(unittest.TestCase):
6 | # 测试用例运行之前
7 | def setUp(self) -> None:
8 | print('前置条件')
9 |
10 | # 测试用例运行之后
11 | def tearDown(self) -> None:
12 | print('后置条件')
13 | # 定义测试用例
14 |
15 |
16 | def test_add(self):
17 | self.assertEqual(3,3)
18 |
19 | if __name__ == '__main__':
20 | unittest.main()
--------------------------------------------------------------------------------
/chapter14/booking_system/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9
2 | ENV ASYNC_DB_DRIVER=postgresql+asyncpg SYNC_DB_DRIVER=postgresql DB_PASSWORD=123456
3 | COPY ./requirements.txt ./requirements.txt
4 | RUN pip install --upgrade -r ./requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
5 | COPY ./ .
6 |
7 | CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "12510"]
8 |
--------------------------------------------------------------------------------
/chapter14/booking_system/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/apis/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/doctor/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_docrot = APIRouter(prefix='/api/v1',tags=["医生信息模块"],include_in_schema=True)
3 | from ..api import doctor_api
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/doctor/dependencies/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/apis/doctor/dependencies/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/doctor/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class SchedulingInfo(BaseModel):
5 | # 预约医生编号
6 | dno: str
7 | # 预约时间
8 | start_time: str = None
9 |
10 |
11 | class MakeReserveOrderForm(BaseModel):
12 | # 预约医生编号
13 | dno: str
14 | # 预约医生排号时段
15 | nsindex: str
16 |
17 |
18 | class PayReserveOrderForm(BaseModel):
19 | # 预约医生编号
20 | dno: str
21 | # 预约医生排号时段
22 | nsindex: str
23 | # 预约人信息
24 | visit_uname: str
25 | visit_uphone: str
26 | visit_uopenid: str = None
27 | visit_usex: str
28 | visit_uage: str
29 |
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/hospital/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/apis/hospital/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/hospital/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_hospital = APIRouter(prefix='/api/v1',tags=["医院信息模块"])
3 | # 導入模塊
4 | from apis.hospital.api import get_hospital_info
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/hospital/api/get_hospital_info.py:
--------------------------------------------------------------------------------
1 | from fastapi import Depends
2 | from apis.hospital.repository import HospitalServeries
3 | from db.async_database import depends_get_db_session
4 | from db.async_database import AsyncSession
5 | from exts.responses.json_response import Success
6 | from ..api import router_hospital
7 |
8 |
9 | @router_hospital.get("/hospital_info", summary='获取医院信息')
10 | async def callbadk(db_session: AsyncSession = Depends(depends_get_db_session)):
11 | info = await HospitalServeries.get_hospital_info(db_session, id=1)
12 | return Success(result=info)
13 |
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/hospital/repository/__init__.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy import select, update, delete
2 | from sqlalchemy.ext.asyncio import AsyncSession
3 | from db.models import Hospitalinfo
4 | from db.async_database import async_engine, Base
5 |
6 |
7 | class HospitalServeries:
8 |
9 | @staticmethod
10 | async def get_hospital_info(async_session: AsyncSession, id: int):
11 | _result = await async_session.execute(
12 | select(Hospitalinfo.name, Hospitalinfo.describe, Hospitalinfo.describeimages).where(Hospitalinfo.id == id))
13 | scalars_result = _result.first()
14 | # scalars_result = _result.scalars().first()
15 | return scalars_result
16 |
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/payorders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/apis/payorders/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/payorders/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_payorders = APIRouter(prefix='/api/v1',tags=["支付订单模块"])
3 | from apis.payorders.api import doctor_reserve_order
4 | from apis.payorders.api import payback_reserve_order
5 | from apis.payorders.api import reserve_order_info
6 | from apis.payorders.api import doctor_reserve_reorder
7 | from apis.payorders.api import doctor_order_check
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/payorders/dependencies/__init__.py:
--------------------------------------------------------------------------------
1 | from starlette.requests import Request
2 |
3 | def get_client_ip(request: Request):
4 | """
5 | 获取客户端真实ip
6 | :param request:
7 | :return:
8 | """
9 | forwarded = request.headers.get("X-Forwarded-For")
10 | if forwarded:
11 | return forwarded.split(",")[0]
12 | return request.client.host
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/userorders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/apis/userorders/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/userorders/api/__init__.py:
--------------------------------------------------------------------------------
1 | from fastapi import APIRouter
2 | router_userorders = APIRouter(prefix='/api/v1', tags=["用户订单模块"])
3 | from apis.userorders.api import refund_reserve_order, unpay_reserve_order, user_order_info, user_order_list, \
4 | wxauth_login
5 |
--------------------------------------------------------------------------------
/chapter14/booking_system/apis/userorders/api/user_order_list.py:
--------------------------------------------------------------------------------
1 | from fastapi import Depends
2 | from db.async_database import depends_get_db_session
3 | from db.async_database import AsyncSession
4 | from exts.responses.json_response import Success, Fail
5 | from ..api import router_userorders
6 | from ..schemas import UserOrderIonfoListForm
7 | from ..repository import Serveries
8 |
9 | @router_userorders.post("/user_order_list", summary='用户自己订单列表')
10 | async def callbadk(forms: UserOrderIonfoListForm, db_session: AsyncSession = Depends(depends_get_db_session)):
11 | # 检测用户的有消息
12 | # 判断当前用户是否已经被拉黑啦,禁用了!
13 | result = await Serveries.get_order_info_list_by_visit_uopenid_select(db_session,visit_uopenid=forms.visit_uopenid,statue=forms.statue)
14 | # is_reserve -属性 1:表示可以点击预约 2:有排班记录,但是已预约满
15 | return Success(api_code=200, result=result, message='查询成功') if result else Fail(api_code=200, result=None, message='无此订单状态列表信息!')
16 |
--------------------------------------------------------------------------------
/chapter14/booking_system/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/config/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/db/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/db/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/exts/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/requestvar/bing.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
24 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/responses/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/evn python
2 | # -*- coding: utf-8 -*-
3 | """
4 | -------------------------------------------------
5 | 文件名称 : __init__.py
6 | 文件功能描述 : 功能描述
7 | 创建人 : 小钟同学
8 | 创建时间 : 2021/9/23
9 | -------------------------------------------------
10 | 修改描述-2021/9/23:
11 | -------------------------------------------------
12 | """
13 | from . import json_response
14 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, unicode_literals
2 |
3 | import logging
4 |
5 | from exts.wechatpy.client import WeChatClient # NOQA
6 | from exts.wechatpy.component import ComponentOAuth, WeChatComponent # NOQA
7 | from exts.wechatpy.exceptions import WeChatClientException, WeChatException, WeChatOAuthException, WeChatPayException # NOQA
8 | from exts.wechatpy.oauth import WeChatOAuth # NOQA
9 | from exts.wechatpy.parser import parse_message # NOQA
10 | from exts.wechatpy.pay import WeChatPay # NOQA
11 | from exts.wechatpy.replies import create_reply # NOQA
12 |
13 | __version__ = '1.8.2'
14 | __author__ = 'messense'
15 |
16 | # Set default logging handler to avoid "No handler found" warnings.
17 | try: # Python 2.7+
18 | from logging import NullHandler
19 | except ImportError:
20 | class NullHandler(logging.Handler):
21 | def emit(self, record):
22 | pass
23 |
24 | logging.getLogger(__name__).addHandler(NullHandler())
25 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/_compat.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | wechatpy._compat
4 | ~~~~~~~~~~~~~~~~~
5 |
6 | This module makes it easy for wechatpy to run on both Python 2 and 3.
7 |
8 | :copyright: (c) 2014 by messense.
9 | :license: MIT, see LICENSE for more details.
10 | """
11 | from __future__ import absolute_import, unicode_literals
12 | import sys
13 | import six
14 | import warnings
15 |
16 | warnings.warn("Module `wechatpy._compat` is deprecated, will be removed in 2.0"
17 | "use `wechatpy.utils` instead",
18 | DeprecationWarning, stacklevel=2)
19 |
20 | from exts.wechatpy.utils import get_querystring
21 | from exts.wechatpy.utils import json
22 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/client/api/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class BaseWeChatAPI(object):
6 | """ WeChat API base class """
7 |
8 | def __init__(self, client=None):
9 | self._client = client
10 |
11 | def _get(self, url, **kwargs):
12 | if getattr(self, 'API_BASE_URL', None):
13 | kwargs['api_base_url'] = self.API_BASE_URL
14 | return self._client.get(url, **kwargs)
15 |
16 | def _post(self, url, **kwargs):
17 | if getattr(self, 'API_BASE_URL', None):
18 | kwargs['api_base_url'] = self.API_BASE_URL
19 |
20 | print("当前URL",url)
21 | return self._client.post(url, **kwargs)
22 |
23 | @property
24 | def access_token(self):
25 | return self._client.access_token
26 |
27 | @property
28 | def session(self):
29 | return self._client.session
30 |
31 | @property
32 | def appid(self):
33 | return self._client.appid
34 |
35 | @property
36 | def secret(self):
37 | return self._client.secret
38 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/client/api/merchant/category.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantCategory(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def get_sub_categories(self, cate_id):
11 | res = self._post(
12 | 'merchant/category/getsub',
13 | data={'cate_id': cate_id},
14 | result_processor=lambda x: x['cate_list']
15 | )
16 | return res
17 |
18 | def get_sku_list(self, cate_id):
19 | res = self._post(
20 | 'merchant/category/getsku',
21 | data={'cate_id': cate_id},
22 | result_processor=lambda x: x['sku_table']
23 | )
24 | return res
25 |
26 | def get_properties(self, cate_id):
27 | res = self._post(
28 | 'merchant/category/getproperty',
29 | data={'cate_id': cate_id},
30 | result_processor=lambda x: x['properties']
31 | )
32 | return res
33 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/client/api/merchant/common.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantCommon(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def upload_image(self, filename, image_data):
11 | res = self._post(
12 | 'merchant/common/upload_img',
13 | params={
14 | 'filename': filename
15 | },
16 | data=image_data,
17 | result_processor=lambda x: x['image_url']
18 | )
19 | return res
20 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/client/api/merchant/stock.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.client.api.base import BaseWeChatAPI
4 |
5 |
6 | class MerchantStock(BaseWeChatAPI):
7 |
8 | API_BASE_URL = 'https://api.weixin.qq.com/'
9 |
10 | def add(self, product_id, quantity, sku_info=''):
11 | return self._post(
12 | 'merchant/stock/add',
13 | data={
14 | 'product_id': product_id,
15 | 'quantity': quantity,
16 | 'sku_info': sku_info
17 | }
18 | )
19 |
20 | def reduce(self, product_id, quantity, sku_info=''):
21 | return self._post(
22 | 'merchant/stock/reduce',
23 | data={
24 | 'product_id': product_id,
25 | 'quantity': quantity,
26 | 'sku_info': sku_info
27 | }
28 | )
29 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/crypto/cryptography.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
4 | from cryptography.hazmat.backends import default_backend
5 |
6 |
7 | class WeChatCipher(object):
8 |
9 | def __init__(self, key, iv=None):
10 | iv = iv or key[:16]
11 | backend = default_backend()
12 | self.cipher = Cipher(
13 | algorithms.AES(key),
14 | modes.CBC(iv),
15 | backend=backend
16 | )
17 |
18 | def encrypt(self, plaintext):
19 | encryptor = self.cipher.encryptor()
20 | return encryptor.update(plaintext) + encryptor.finalize()
21 |
22 | def decrypt(self, ciphertext):
23 | decryptor = self.cipher.decryptor()
24 | return decryptor.update(ciphertext) + decryptor.finalize()
25 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/crypto/pkcs7.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.utils import to_binary, byte2int
4 |
5 |
6 | class PKCS7Encoder(object):
7 | block_size = 32
8 |
9 | @classmethod
10 | def encode(cls, text):
11 | length = len(text)
12 | padding_count = cls.block_size - length % cls.block_size
13 | if padding_count == 0:
14 | padding_count = cls.block_size
15 | padding = to_binary(chr(padding_count))
16 | return text + padding * padding_count
17 |
18 | @classmethod
19 | def decode(cls, decrypted):
20 | padding = byte2int(decrypted[-1])
21 | if padding < 1 or padding > 32:
22 | padding = 0
23 | return decrypted[:-padding]
24 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/crypto/pycrypto.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from Crypto.Cipher import AES
4 |
5 |
6 | class WeChatCipher(object):
7 |
8 | def __init__(self, key, iv=None):
9 | iv = iv or key[:16]
10 | self.cipher = AES.new(key, AES.MODE_CBC, iv)
11 |
12 | def encrypt(self, plaintext):
13 | return self.cipher.encrypt(plaintext)
14 |
15 | def decrypt(self, ciphertext):
16 | return self.cipher.decrypt(ciphertext)
17 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/enterprise/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.enterprise.client import WeChatClient # NOQA
5 | from exts.wechatpy.enterprise.crypto import WeChatCrypto # NOQA
6 | from exts.wechatpy.enterprise.parser import parse_message # NOQA
7 | from exts.wechatpy.enterprise.replies import create_reply # NOQA
8 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/enterprise/client/api/misc.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.client.api.base import BaseWeChatAPI
5 |
6 |
7 | class WeChatMisc(BaseWeChatAPI):
8 |
9 | def get_wechat_ips(self):
10 | """
11 | 获取企业微信服务器的ip段
12 |
13 | https://work.weixin.qq.com/api/doc#90000/90135/90238/%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84ip%E6%AE%B5
14 |
15 | :return: 企业微信回调的IP段
16 | """
17 | res = self._get('getcallbackip')
18 | return res['ip_list']
19 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/enterprise/client/api/shakearound.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.client.api.base import BaseWeChatAPI
5 |
6 |
7 | class WeChatShakeAround(BaseWeChatAPI):
8 |
9 | def get_shake_info(self, ticket):
10 | """
11 | 获取摇周边的设备及用户信息
12 |
13 | https://qydev.weixin.qq.com/wiki/index.php?title=获取设备及用户信息
14 |
15 | :param ticket: 摇周边业务的ticket,可在摇到的 URL 中得到,ticket 生效时间为30分钟
16 | :return: 设备及用户信息
17 | """
18 | res = self._post(
19 | 'shakearound/getshakeinfo',
20 | data={
21 | 'ticket': ticket
22 | }
23 | )
24 | return res['data']
25 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/enterprise/exceptions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from exts.wechatpy.exceptions import WeChatException
5 |
6 |
7 | class InvalidCorpIdException(WeChatException):
8 |
9 | def __init__(self, errcode=-40005, errmsg='Invalid corp_id'):
10 | super(InvalidCorpIdException, self).__init__(errcode, errmsg)
11 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/enterprise/parser.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | import xmltodict
5 |
6 | from exts.wechatpy.enterprise.events import EVENT_TYPES
7 | from exts.wechatpy.enterprise.messages import MESSAGE_TYPES
8 | from exts.wechatpy.messages import UnknownMessage
9 | from exts.wechatpy.utils import to_text
10 |
11 |
12 | def parse_message(xml):
13 | if not xml:
14 | return
15 | message = xmltodict.parse(to_text(xml))['xml']
16 | message_type = message['MsgType'].lower()
17 | if message_type == 'event':
18 | event_type = message['Event'].lower()
19 | message_class = EVENT_TYPES.get(event_type, UnknownMessage)
20 | else:
21 | message_class = MESSAGE_TYPES.get(message_type, UnknownMessage)
22 | return message_class(message)
23 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/pay/api/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.pay.api.redpack import WeChatRedpack # NOQA
4 | from exts.wechatpy.pay.api.transfer import WeChatTransfer # NOQA
5 | from exts.wechatpy.pay.api.coupon import WeChatCoupon # NOQA
6 | from exts.wechatpy.pay.api.order import WeChatOrder # NOQA
7 | from exts.wechatpy.pay.api.refund import WeChatRefund # NOQA
8 | from exts.wechatpy.pay.api.tools import WeChatTools # NOQA
9 | from exts.wechatpy.pay.api.jsapi import WeChatJSAPI # NOQA
10 | from exts.wechatpy.pay.api.micropay import WeChatMicroPay # NOQA
11 | from exts.wechatpy.pay.api.withhold import WeChatWithhold # NOQA
12 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/pay/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class BaseWeChatPayAPI(object):
6 | """ WeChat Pay API base class """
7 | def __init__(self, client=None):
8 | self._client = client
9 |
10 | def _get(self, url, **kwargs):
11 | if getattr(self, 'API_BASE_URL', None):
12 | kwargs['api_base_url'] = self.API_BASE_URL
13 | return self._client.get(url, **kwargs)
14 |
15 | def _post(self, url, **kwargs):
16 | if getattr(self, 'API_BASE_URL', None):
17 | kwargs['api_base_url'] = self.API_BASE_URL
18 | return self._client.post(url, **kwargs)
19 |
20 | @property
21 | def appid(self):
22 | return self._client.appid
23 |
24 | @property
25 | def sub_appid(self):
26 | return self._client.sub_appid
27 |
28 | @property
29 | def mch_id(self):
30 | return self._client.mch_id
31 |
32 | @property
33 | def sub_mch_id(self):
34 | return self._client.sub_mch_id
35 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/session/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 |
4 |
5 | class SessionStorage(object):
6 |
7 | def get(self, key, default=None):
8 | raise NotImplementedError()
9 |
10 | def set(self, key, value, ttl=None):
11 | raise NotImplementedError()
12 |
13 | def delete(self, key):
14 | raise NotImplementedError()
15 |
16 | def __getitem__(self, key):
17 | self.get(key)
18 |
19 | def __setitem__(self, key, value):
20 | self.set(key, value)
21 |
22 | def __delitem__(self, key):
23 | self.delete(key)
24 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/session/memorystorage.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.session import SessionStorage
4 |
5 |
6 | class MemoryStorage(SessionStorage):
7 |
8 | def __init__(self):
9 | self._data = {}
10 |
11 | def get(self, key, default=None):
12 | return self._data.get(key, default)
13 |
14 | def set(self, key, value, ttl=None):
15 | if value is None:
16 | return
17 | self._data[key] = value
18 |
19 | def delete(self, key):
20 | self._data.pop(key, None)
21 |
--------------------------------------------------------------------------------
/chapter14/booking_system/exts/wechatpy/session/shovestorage.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import absolute_import, unicode_literals
3 | from exts.wechatpy.session import SessionStorage
4 |
5 |
6 | class ShoveStorage(SessionStorage):
7 |
8 | def __init__(self, shove, prefix='wechatpy'):
9 | self.shove = shove
10 | self.prefix = prefix
11 |
12 | def key_name(self, key):
13 | return '{0}:{1}'.format(self.prefix, key)
14 |
15 | def get(self, key, default=None):
16 | key = self.key_name(key)
17 | try:
18 | return self.shove[key]
19 | except KeyError:
20 | return default
21 |
22 | def set(self, key, value, ttl=None):
23 | if value is None:
24 | return
25 |
26 | key = self.key_name(key)
27 | self.shove[key] = value
28 |
29 | def delete(self, key):
30 | key = self.key_name(key)
31 | try:
32 | del self.shove[key]
33 | except KeyError:
34 | pass
35 |
--------------------------------------------------------------------------------
/chapter14/booking_system/main.py:
--------------------------------------------------------------------------------
1 | from app import creat_app
2 | app =creat_app()
3 | if __name__ == "__main__":
4 | import uvicorn
5 | import os
6 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
7 | print(app_modeel_name)
8 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
9 |
10 |
11 | # tree -I "node_modules|cache|test_*"
12 | # tree -I "__pycache__"
--------------------------------------------------------------------------------
/chapter14/booking_system/middlewares/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/middlewares/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/middlewares/loger/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/middlewares/loger/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/middlewares/loger/bing.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
24 |
--------------------------------------------------------------------------------
/chapter14/booking_system/plugins/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/plugins/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/plugins/base.py:
--------------------------------------------------------------------------------
1 | import fastapi
2 | import pydantic
3 | import typing
4 | import abc
5 |
6 | class PluginBase(abc.ABC):
7 |
8 | def __init__(self,app: fastapi.FastAPI = None,config: pydantic.BaseSettings = None):
9 | if app is not None:
10 | self.init_app(app)
11 |
12 | @abc.abstractmethod
13 | def init_app(self,app: fastapi.FastAPI,config: pydantic.BaseSettings = None,*args,**kwargs) -> None:
14 | raise NotImplementedError('需要实现初始化')
15 |
--------------------------------------------------------------------------------
/chapter14/booking_system/requirements.txt:
--------------------------------------------------------------------------------
1 | aio-pika==8.0.3
2 | aiormq==6.3.4
3 | anyio==3.6.1
4 | asgiref==3.5.2
5 | asyncpg==0.26.0
6 | certifi==2022.6.15
7 | charset-normalizer==2.1.0
8 | click==8.1.3
9 | colorama==0.4.5
10 | dnspython==2.2.1
11 | email-validator==1.2.1
12 | fastapi==0.79.0
13 | greenlet==1.1.2
14 | gunicorn==20.1.0
15 | h11==0.13.0
16 | httptools==0.4.0
17 | idna==3.3
18 | itsdangerous==2.1.2
19 | Jinja2==3.1.2
20 | MarkupSafe==2.1.1
21 | multidict==6.0.2
22 | optionaldict==0.1.2
23 | orjson==3.7.8
24 | pamqp==3.2.0
25 | pika==1.3.0
26 | psycopg2==2.9.3
27 | pycryptodome==3.15.0
28 | pydantic==1.9.1
29 | python-dotenv==0.20.0
30 | python-multipart==0.0.5
31 | PyYAML==6.0
32 | requests==2.28.1
33 | six==1.16.0
34 | sniffio==1.2.0
35 | SQLAlchemy==1.4.39
36 | starlette==0.19.1
37 | typing_extensions==4.3.0
38 | ujson==5.4.0
39 | urllib3==1.26.10
40 | uvicorn==0.17.6
41 | watchgod==0.8.2
42 | websockets==10.3
43 | xmltodict==0.13.0
44 | yarl==1.7.2
45 |
--------------------------------------------------------------------------------
/chapter14/booking_system/testcase/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/testcase/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/testcase/test_async_api_v2.py:
--------------------------------------------------------------------------------
1 | # from uuid import UUID
2 | #
3 | import pytest
4 | from httpx import AsyncClient
5 | pytestmark = pytest.mark.anyio
6 |
7 | async def test_hospital_info(async_client: AsyncClient):
8 | response = await async_client.get("/api/v1/hospital_info")
9 | print('response', response.text)
10 | assert response.status_code == 200
11 |
12 |
13 | async def test_doctor_list(async_client: AsyncClient):
14 | response = await async_client.get("/api/v1/doctor_list")
15 | print('response', response.text)
16 | assert response.status_code == 200
--------------------------------------------------------------------------------
/chapter14/booking_system/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/utils/__init__.py
--------------------------------------------------------------------------------
/chapter14/booking_system/utils/cast_helper.py:
--------------------------------------------------------------------------------
1 | def add(a,b):
2 | return a+b;
--------------------------------------------------------------------------------
/chapter14/booking_system/utils/run_with_asyncio.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 | import asyncio
3 | from functools import wraps
4 | from typing import Any, Awaitable, Callable, TypeVar
5 | T = TypeVar("T")
6 | __all__ = ["run_with_asyncio"]
7 | def run_with_asyncio(f: Callable[..., Awaitable[T]]) -> Callable[..., T]:
8 | @wraps(f)
9 | def wrapper(*args: Any, **kwargs: Any) -> T:
10 | print("pajinlail")
11 | return asyncio.run(f(*args, **kwargs))
12 | return wrapper
--------------------------------------------------------------------------------
/chapter14/booking_system/wxchatsdk/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter14/booking_system/wxchatsdk/__init__.py
--------------------------------------------------------------------------------
/chapter15/Fastapi_cProfile/.prof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/Fastapi_cProfile/.prof
--------------------------------------------------------------------------------
/chapter15/async_sync_change/main_asgiref_async_to_sync.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from fastapi import FastAPI,Request
4 | from fastapi.responses import PlainTextResponse
5 | from fastapi.params import Body
6 |
7 |
8 | app = FastAPI()
9 |
10 |
11 | @app.post("/get/access_token")
12 | def access_token(request:Request,name=Body(...)):
13 | # print(reques.body())
14 | from asgiref.sync import async_to_sync
15 | body = async_to_sync(request.body)()
16 | print(body)
17 | return PlainTextResponse(body.decode(encoding='utf-8'))
18 |
19 |
20 | if __name__ == '__main__':
21 | import uvicorn
22 | uvicorn.run('main:app', host="127.0.0.1", port=8100, debug=True, reload=True)
--------------------------------------------------------------------------------
/chapter15/async_sync_change/main_asgiref_sync_to_async.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from fastapi import FastAPI,Request
4 |
5 | from fastapi.responses import PlainTextResponse,HTMLResponse
6 | from asgiref.sync import sync_to_async
7 | import requests
8 | # 定义我们的APP服务对象
9 | app = FastAPI()
10 |
11 | def getdata():
12 | return requests.get('http://www.baidu.com').text
13 |
14 |
15 |
16 |
17 | @app.get("/get/access_token")
18 | async def access_token():
19 | asds= await sync_to_async(func=getdata)()
20 | return HTMLResponse(asds)
21 |
22 |
23 | if __name__ == "__main__":
24 | import uvicorn
25 | import os
26 |
27 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
28 | print(app_modeel_name)
29 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
30 |
31 |
32 |
--------------------------------------------------------------------------------
/chapter15/async_sync_change/main_asyncer_asyncify.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI,Request
2 | from fastapi.responses import PlainTextResponse,HTMLResponse
3 | from asyncer import asyncify
4 | import requests
5 | # 定义我们的APP服务对象
6 | app = FastAPI()
7 |
8 | def do_sync_work(name):
9 | return requests.get(f'http://www.baidu.com?name={name}').text
10 |
11 | @app.get("/get/access_token")
12 | async def access_token(request:Request):
13 | message = await asyncify(do_sync_work)(name="World")
14 | return HTMLResponse(message)
15 |
16 |
17 | if __name__ == '__main__':
18 | import uvicorn
19 | uvicorn.run('main:app', host="127.0.0.1", port=8100, debug=True, reload=True)
20 |
--------------------------------------------------------------------------------
/chapter15/async_sync_change/main_asyncer_syncify.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI,Request
2 | from fastapi.responses import PlainTextResponse
3 | from fastapi.params import Body
4 | from fastapi.background import BackgroundTasks
5 | from asyncer import asyncify,syncify
6 |
7 | app = FastAPI()
8 |
9 | @app.post("/get/access_token")
10 | def access_token(request:Request,name=Body(...)):
11 | body = syncify(request.body)()
12 | print(body)
13 | return PlainTextResponse(body.decode(encoding='utf-8'))
14 |
15 | if __name__ == '__main__':
16 | import uvicorn
17 | uvicorn.run('main:app', host="127.0.0.1", port=8100, debug=True, reload=True)
18 |
19 |
--------------------------------------------------------------------------------
/chapter15/async_wrapper/.runtest.prof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/async_wrapper/.runtest.prof
--------------------------------------------------------------------------------
/chapter15/cProfile/c_profile_text_run.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 |
4 | def randomlist(n):
5 | lists = []
6 | l = [random.random() for i in range(n)]
7 | l.sort()
8 | for v in l:
9 | lists.append(v)
10 | return lists
11 |
12 |
13 |
14 |
15 | if __name__ == "__main__":
16 | randomlist(20)
--------------------------------------------------------------------------------
/chapter15/cProfile/crpresutl.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/cProfile/crpresutl.svg
--------------------------------------------------------------------------------
/chapter15/cProfile/runtest.prof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/cProfile/runtest.prof
--------------------------------------------------------------------------------
/chapter15/cProfile/runtest_profile.stats:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/cProfile/runtest_profile.stats
--------------------------------------------------------------------------------
/chapter15/cProfile/runtest_profile_stats_run.py:
--------------------------------------------------------------------------------
1 | import pstats
2 | p = pstats.Stats("runtest_profile.stats")
3 | p.sort_stats("cumulative") # 和显示明细一样
4 | # p.print_stats()
5 | p.print_callers() # 可以显示函数被哪些函数调用
6 |
--------------------------------------------------------------------------------
/chapter15/contextvar_request/bind_.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
--------------------------------------------------------------------------------
/chapter15/contextvar_request/main_class.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 | from fastapi.responses import JSONResponse
6 |
7 | from chapter15.contextvar_request.request import request_var, request
8 |
9 | app = FastAPI()
10 |
11 |
12 | @app.middleware("http")
13 | async def add_process_time_header(request: Request, call_next):
14 | token = request_var.set(request)
15 | try:
16 | response = await call_next(request)
17 | return response
18 | finally:
19 | request_var.reset(token)
20 |
21 |
22 |
23 |
24 | @app.post('/index')
25 | async def index():
26 | # 这里应该使用事务处理
27 | print(request.headers)
28 | return JSONResponse({
29 | "code": 200,
30 | "msg": "成功"
31 | })
32 |
33 | if __name__ == "__main__":
34 | import uvicorn
35 | import os
36 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
37 | print(app_modeel_name)
38 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
39 |
--------------------------------------------------------------------------------
/chapter15/contextvar_request/request.py:
--------------------------------------------------------------------------------
1 | from contextvars import ContextVar
2 | from fastapi import Request
3 | from chapter15.contextvar_request.bind_ import bind_contextvar
4 |
5 | request_var: ContextVar[Request] = ContextVar("request")
6 | request:Request = bind_contextvar(request_var)
--------------------------------------------------------------------------------
/chapter15/depends/main_class.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 |
6 | app = FastAPI()
7 |
8 |
9 | class AuthCheck:
10 | def __init__(self, role: str):
11 | self.role = role
12 |
13 | @app.get("/auth_check")
14 | def auth_check(role: dict = Depends(AuthCheck)):
15 | return role
16 |
17 | if __name__ == "__main__":
18 | import uvicorn
19 | import os
20 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
21 | print(app_modeel_name)
22 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
23 |
--------------------------------------------------------------------------------
/chapter15/depends/main_class_call.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 |
6 | app = FastAPI()
7 |
8 |
9 | class AuthCheck:
10 | def __init__(self, role_name: str):
11 | self.role_name = role_name
12 |
13 | def __call__(self,):
14 | print("当前角色是:",self.role_name)
15 | if self.role_name =='admin':
16 | return "管理员"
17 | return "普通用户"
18 |
19 | @app.get("/auth_check")
20 | def auth_check(role: str = Depends(AuthCheck(role_name="admin"))):
21 | return role
22 |
23 | if __name__ == "__main__":
24 | import uvicorn
25 | import os
26 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
27 | print(app_modeel_name)
28 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
29 |
--------------------------------------------------------------------------------
/chapter15/depends/main_class_security_scopes.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from fastapi.security import SecurityScopes
3 | from fastapi import Security
4 |
5 | app = FastAPI()
6 |
7 |
8 | class AuthCheck:
9 | def __init__(self, security_scopes: SecurityScopes, role: str):
10 | print("传入的参数:", security_scopes.scopes)
11 | self.role = role
12 |
13 |
14 | @app.get("/auth_check2")
15 | def auth_check(role: str = Security(AuthCheck, scopes=["admin"])):
16 | return role
17 |
18 |
19 | if __name__ == "__main__":
20 | import uvicorn
21 | import os
22 |
23 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
24 | print(app_modeel_name)
25 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
26 |
--------------------------------------------------------------------------------
/chapter15/depends/main_fun.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 |
6 | app = FastAPI()
7 |
8 |
9 | def auth_check(role:str):
10 | return role
11 |
12 | @app.get("/auth_check")
13 | def auth_check(role: str = Depends(auth_check)):
14 | return role
15 | if __name__ == "__main__":
16 | import uvicorn
17 | import os
18 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
19 | print(app_modeel_name)
20 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
21 |
--------------------------------------------------------------------------------
/chapter15/depends/main_fun_security_scopes.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from fastapi.security import SecurityScopes
3 | from fastapi import Security
4 |
5 | app = FastAPI()
6 |
7 |
8 | def auth_check(security_scopes: SecurityScopes):
9 | print("传入的参数:", security_scopes.scopes)
10 | if security_scopes.scopes[0] == 'admin':
11 | return "管理者"
12 | return "普通用户"
13 |
14 |
15 | @app.get("/auth_check")
16 | def auth_check(role: str = Security(auth_check, scopes=["admin"])):
17 | return role
18 |
19 |
20 | if __name__ == "__main__":
21 | import uvicorn
22 | import os
23 |
24 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
25 | print(app_modeel_name)
26 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
27 |
--------------------------------------------------------------------------------
/chapter15/fastapi_cache/uu.py:
--------------------------------------------------------------------------------
1 | x=3
2 |
3 | print(x)
4 | y=2
5 | k=x+y
6 | print(k)
7 | x=5
8 | y=7
9 | print(x*y)
10 |
11 | def jiafa(x,y):
12 | return x+ y
13 |
14 | print(jiafa(2,4))
15 |
16 |
17 | print(jiafa(2,4333))
18 |
--------------------------------------------------------------------------------
/chapter15/model_sort/main_asyncer_syncify.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 |
3 | app = FastAPI()
4 |
5 | from pydantic import BaseModel
6 | from typing import Optional
7 |
8 |
9 | class Item(BaseModel):
10 |
11 | def __new__(cls, *args, **kwargs):
12 | instance = super().__new__(cls)
13 | # 对当前__fields__重新进行排序
14 | cls.__fields__ = {key: cls.__fields__[key] for key in sorted(cls.__fields__.keys())}
15 | return instance
16 |
17 | desc: Optional[str] = None
18 | price: str
19 | age: str
20 | aname: str
21 |
22 |
23 | @app.post('/items/', response_model=Item)
24 | async def getitem(item: Item):
25 | return item
26 |
27 |
28 | if __name__ == "__main__":
29 | import uvicorn
30 | import os
31 |
32 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
33 | print(app_modeel_name)
34 | uvicorn.run(f"{app_modeel_name}:app", reload=True)
35 |
--------------------------------------------------------------------------------
/chapter15/sentry/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/sentry/__init__.py
--------------------------------------------------------------------------------
/chapter15/sentry/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 |
3 | import sentry_sdk
4 |
5 | from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
6 |
7 | sentry_sdk.init(
8 | dsn="http://8360febb6aae46deafde65afd092e481@192.168.126.130:9000/2",
9 | # Set traces_sample_rate to 1.0 to capture 100%
10 | # of transactions for performance monitoring.
11 | # We recommend adjusting this value in production,
12 | traces_sample_rate=1.0,
13 | )
14 |
15 | app = FastAPI()
16 |
17 | @app.get("/sentry-debug")
18 | async def trigger_error():
19 | division_by_zero = 1 / 0
20 |
21 |
22 | if __name__ == "__main__":
23 | import uvicorn
24 | import os
25 |
26 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
27 | print(app_modeel_name)
28 | uvicorn.run(f"{app_modeel_name}:app", reload=True)
--------------------------------------------------------------------------------
/chapter15/smtplib/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter15/smtplib/test.jpg
--------------------------------------------------------------------------------
/chapter15/smtplib/test1.txt:
--------------------------------------------------------------------------------
1 | 我是测试文件的内容!
--------------------------------------------------------------------------------
/chapter15/smtplib/test2.txt:
--------------------------------------------------------------------------------
1 | 我是测试文件的内容!
--------------------------------------------------------------------------------
/chapter16/async_sync_change/main_asgiref_async_to_sync.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from fastapi import FastAPI,Request
4 | from fastapi.responses import PlainTextResponse
5 | from fastapi.params import Body
6 |
7 |
8 | app = FastAPI()
9 |
10 |
11 | @app.post("/get/access_token")
12 | def access_token(request:Request,name=Body(...)):
13 | # print(reques.body())
14 | from asgiref.sync import async_to_sync
15 | body = async_to_sync(request.body)()
16 | print(body)
17 | return PlainTextResponse(body.decode(encoding='utf-8'))
18 |
19 |
20 | if __name__ == '__main__':
21 | import uvicorn
22 | uvicorn.run('main:app', host="127.0.0.1", port=8100, debug=True, reload=True)
--------------------------------------------------------------------------------
/chapter16/async_sync_change/main_asgiref_sync_to_async.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from fastapi import FastAPI,Request
4 |
5 | from fastapi.responses import PlainTextResponse,HTMLResponse
6 | from asgiref.sync import sync_to_async
7 | import requests
8 | # 定义我们的APP服务对象
9 | app = FastAPI()
10 |
11 | def getdata():
12 | return requests.get('http://www.baidu.com').text
13 |
14 |
15 |
16 |
17 | @app.get("/get/access_token")
18 | async def access_token():
19 | asds= await sync_to_async(func=getdata)()
20 | return HTMLResponse(asds)
21 |
22 |
23 | if __name__ == "__main__":
24 | import uvicorn
25 | import os
26 |
27 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
28 | print(app_modeel_name)
29 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
30 |
31 |
32 |
--------------------------------------------------------------------------------
/chapter16/async_sync_change/main_asyncer_asyncify.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI,Request
2 | from fastapi.responses import PlainTextResponse,HTMLResponse
3 | from asyncer import asyncify
4 | import requests
5 | # 定义我们的APP服务对象
6 | app = FastAPI()
7 |
8 | def do_sync_work(name):
9 | return requests.get(f'http://www.baidu.com?name={name}').text
10 |
11 | @app.get("/get/access_token")
12 | async def access_token(request:Request):
13 | message = await asyncify(do_sync_work)(name="World")
14 | return HTMLResponse(message)
15 |
16 |
17 | if __name__ == '__main__':
18 | import uvicorn
19 | uvicorn.run('main:app', host="127.0.0.1", port=8100, debug=True, reload=True)
20 |
--------------------------------------------------------------------------------
/chapter16/async_sync_change/main_asyncer_syncify.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI,Request
2 | from fastapi.responses import PlainTextResponse
3 | from fastapi.params import Body
4 | from fastapi.background import BackgroundTasks
5 | from asyncer import asyncify,syncify
6 |
7 | app = FastAPI()
8 |
9 | @app.post("/get/access_token")
10 | def access_token(request:Request,name=Body(...)):
11 | body = syncify(request.body)()
12 | print(body)
13 | return PlainTextResponse(body.decode(encoding='utf-8'))
14 |
15 | if __name__ == '__main__':
16 | import uvicorn
17 | uvicorn.run('main:app', host="127.0.0.1", port=8100, debug=True, reload=True)
18 |
19 |
--------------------------------------------------------------------------------
/chapter16/async_wrapper/.runtest.prof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter16/async_wrapper/.runtest.prof
--------------------------------------------------------------------------------
/chapter16/contextvar_request/bind_.py:
--------------------------------------------------------------------------------
1 | def bind_contextvar(contextvar):
2 | class ContextVarBind:
3 | __slots__ = ()
4 |
5 | def __getattr__(self, name):
6 | return getattr(contextvar.get(), name)
7 |
8 | def __setattr__(self, name, value):
9 | setattr(contextvar.get(), name, value)
10 |
11 | def __delattr__(self, name):
12 | delattr(contextvar.get(), name)
13 |
14 | def __getitem__(self, index):
15 | return contextvar.get()[index]
16 |
17 | def __setitem__(self, index, value):
18 | contextvar.get()[index] = value
19 |
20 | def __delitem__(self, index):
21 | del contextvar.get()[index]
22 |
23 | return ContextVarBind()
--------------------------------------------------------------------------------
/chapter16/contextvar_request/main_class.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 | from fastapi.responses import JSONResponse
6 |
7 | from chapter15.contextvar_request.request import request_var, request
8 |
9 | app = FastAPI()
10 |
11 |
12 | @app.middleware("http")
13 | async def add_process_time_header(request: Request, call_next):
14 | token = request_var.set(request)
15 | try:
16 | response = await call_next(request)
17 | return response
18 | finally:
19 | request_var.reset(token)
20 |
21 |
22 |
23 |
24 | @app.post('/index')
25 | async def index():
26 | # 这里应该使用事务处理
27 | print(request.headers)
28 | return JSONResponse({
29 | "code": 200,
30 | "msg": "成功"
31 | })
32 |
33 | if __name__ == "__main__":
34 | import uvicorn
35 | import os
36 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
37 | print(app_modeel_name)
38 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
39 |
--------------------------------------------------------------------------------
/chapter16/contextvar_request/request.py:
--------------------------------------------------------------------------------
1 | from contextvars import ContextVar
2 | from fastapi import Request
3 | from chapter15.contextvar_request.bind_ import bind_contextvar
4 |
5 | request_var: ContextVar[Request] = ContextVar("request")
6 | request:Request = bind_contextvar(request_var)
--------------------------------------------------------------------------------
/chapter16/depends/main_class.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 |
6 | app = FastAPI()
7 |
8 |
9 | class AuthCheck:
10 | def __init__(self, role: str):
11 | self.role = role
12 |
13 | @app.get("/auth_check")
14 | def auth_check(role: dict = Depends(AuthCheck)):
15 | return role
16 |
17 | if __name__ == "__main__":
18 | import uvicorn
19 | import os
20 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
21 | print(app_modeel_name)
22 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
23 |
--------------------------------------------------------------------------------
/chapter16/depends/main_class_call.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 |
6 | app = FastAPI()
7 |
8 |
9 | class AuthCheck:
10 | def __init__(self, role_name: str):
11 | self.role_name = role_name
12 |
13 | def __call__(self,):
14 | print("当前角色是:",self.role_name)
15 | if self.role_name =='admin':
16 | return "管理员"
17 | return "普通用户"
18 |
19 | @app.get("/auth_check")
20 | def auth_check(role: str = Depends(AuthCheck(role_name="admin"))):
21 | return role
22 |
23 | if __name__ == "__main__":
24 | import uvicorn
25 | import os
26 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
27 | print(app_modeel_name)
28 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
29 |
--------------------------------------------------------------------------------
/chapter16/depends/main_class_security_scopes.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from fastapi.security import SecurityScopes
3 | from fastapi import Security
4 |
5 | app = FastAPI()
6 |
7 |
8 | class AuthCheck:
9 | def __init__(self, security_scopes: SecurityScopes, role: str):
10 | print("传入的参数:", security_scopes.scopes)
11 | self.role = role
12 |
13 |
14 | @app.get("/auth_check2")
15 | def auth_check(role: str = Security(AuthCheck, scopes=["admin"])):
16 | return role
17 |
18 |
19 | if __name__ == "__main__":
20 | import uvicorn
21 | import os
22 |
23 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
24 | print(app_modeel_name)
25 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
26 |
--------------------------------------------------------------------------------
/chapter16/depends/main_fun.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from starlette.middleware.base import BaseHTTPMiddleware
4 | from fastapi import FastAPI, Request, Depends
5 |
6 | app = FastAPI()
7 |
8 |
9 | def auth_check(role:str):
10 | return role
11 |
12 | @app.get("/auth_check")
13 | def auth_check(role: str = Depends(auth_check)):
14 | return role
15 | if __name__ == "__main__":
16 | import uvicorn
17 | import os
18 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
19 | print(app_modeel_name)
20 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
21 |
--------------------------------------------------------------------------------
/chapter16/depends/main_fun_security_scopes.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 | from fastapi.security import SecurityScopes
3 | from fastapi import Security
4 |
5 | app = FastAPI()
6 |
7 |
8 | def auth_check(security_scopes: SecurityScopes):
9 | print("传入的参数:", security_scopes.scopes)
10 | if security_scopes.scopes[0] == 'admin':
11 | return "管理者"
12 | return "普通用户"
13 |
14 |
15 | @app.get("/auth_check")
16 | def auth_check(role: str = Security(auth_check, scopes=["admin"])):
17 | return role
18 |
19 |
20 | if __name__ == "__main__":
21 | import uvicorn
22 | import os
23 |
24 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
25 | print(app_modeel_name)
26 | uvicorn.run(f"{app_modeel_name}:app", host='127.0.0.1', reload=True)
27 |
--------------------------------------------------------------------------------
/chapter16/model_sort/main_asyncer_syncify.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 |
3 | app = FastAPI()
4 |
5 | from pydantic import BaseModel
6 | from typing import Optional
7 |
8 |
9 | class Item(BaseModel):
10 |
11 | def __new__(cls, *args, **kwargs):
12 | instance = super().__new__(cls)
13 | # 对当前__fields__重新进行排序
14 | cls.__fields__ = {key: cls.__fields__[key] for key in sorted(cls.__fields__.keys())}
15 | return instance
16 |
17 | desc: Optional[str] = None
18 | price: str
19 | age: str
20 | aname: str
21 |
22 |
23 | @app.post('/items/', response_model=Item)
24 | async def getitem(item: Item):
25 | return item
26 |
27 |
28 | if __name__ == "__main__":
29 | import uvicorn
30 | import os
31 |
32 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
33 | print(app_modeel_name)
34 | uvicorn.run(f"{app_modeel_name}:app", reload=True)
35 |
--------------------------------------------------------------------------------
/chapter16/sentry/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter16/sentry/__init__.py
--------------------------------------------------------------------------------
/chapter16/sentry/main.py:
--------------------------------------------------------------------------------
1 | from fastapi import FastAPI
2 |
3 | import sentry_sdk
4 |
5 | from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
6 |
7 | sentry_sdk.init(
8 | dsn="http://8360febb6aae46deafde65afd092e481@192.168.126.130:9000/2",
9 | # Set traces_sample_rate to 1.0 to capture 100%
10 | # of transactions for performance monitoring.
11 | # We recommend adjusting this value in production,
12 | traces_sample_rate=1.0,
13 | )
14 |
15 | app = FastAPI()
16 |
17 | @app.get("/sentry-debug")
18 | async def trigger_error():
19 | division_by_zero = 1 / 0
20 |
21 |
22 | if __name__ == "__main__":
23 | import uvicorn
24 | import os
25 |
26 | app_modeel_name = os.path.basename(__file__).replace(".py", "")
27 | print(app_modeel_name)
28 | uvicorn.run(f"{app_modeel_name}:app", reload=True)
--------------------------------------------------------------------------------
/chapter16/smtplib/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Gitxieada/fastapi_tutorial/a80a79cf4440669e721b124beb07dbbea2338147/chapter16/smtplib/test.jpg
--------------------------------------------------------------------------------
/chapter16/smtplib/test1.txt:
--------------------------------------------------------------------------------
1 | 我是测试文件的内容!
--------------------------------------------------------------------------------
/chapter16/smtplib/test2.txt:
--------------------------------------------------------------------------------
1 | 我是测试文件的内容!
--------------------------------------------------------------------------------