commit 9f055ef095930cbf87f65b77dde5546c85c31c0f Author: VinokurovVE Date: Mon Sep 23 12:56:23 2024 +0900 First init diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..088b236 --- /dev/null +++ b/.env.template @@ -0,0 +1,5 @@ +DB_URL=mssql+pyodbc://{user}:{password}@{host}/{database_name}?driver=ODBC+Driver+17+for+SQL+Server +HOST=0.0.0.0 +PORT=4444 +SERVER_ROOT= +PREFIX=/agree \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..efa407c --- /dev/null +++ b/.gitignore @@ -0,0 +1,162 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed020c6 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +создать виртуальное окружение +""python3 -m venv .venv""" +подключиться к виртуальному окружению +""".\.venv\Scripts\activate""" +Загрузить библиотеки с файла requirements.txt +"""pip install -r requirements.txt""" +в файле .env.template заменить на ваши данные и сохранить в .env +Запустить приложение +"""main.py""" \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..620e301 --- /dev/null +++ b/main.py @@ -0,0 +1,108 @@ +from fastapi import FastAPI, APIRouter, Request +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import ORJSONResponse, HTMLResponse +from sqlmodel import create_engine, Field, SQLModel, UUID, DateTime, func, Column, text, bindparam +from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER, DATETIME +from sqlalchemy import insert +from dotenv import load_dotenv +from typing import Optional, Sequence +from datetime import datetime +from uuid import UUID +import os +load_dotenv() +DB_URL = os.getenv("DB_URL") +SERVER_ROOT = os.getenv("SERVER_ROOT") +PREFIX = os.getenv("PREFIX") +db_engine = create_engine(DB_URL) + +class Agreement(SQLModel,table=True): + id: Optional[int] = Field(default=None, primary_key=True) + id_account: UUID = Field(sa_column=Column(UNIQUEIDENTIFIER)) + id_personal_account: Optional[int] + date_registration:datetime = Field(sa_column=Column(DATETIME)) + FIO: Optional[str] + phone: Optional[str] + email: Optional[str] + agreement:Optional[bool] = True + agreement_date: Optional[datetime] = Field(sa_column=Column(DATETIME)) + +class AgreementCreate(SQLModel): + id_account: UUID + id_personal_account: Optional[int] + date_registration:datetime + FIO: Optional[str] + phone: Optional[str] + email: Optional[str] + agreement:Optional[bool] = True + agreement_date: Optional[datetime] +SQLModel.metadata.create_all(db_engine, checkfirst=True) + +app = FastAPI(openapi_url = SERVER_ROOT +"/openapi.json", docs_url=SERVER_ROOT+"/docs", default_response_class=ORJSONResponse) +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +router = APIRouter( + prefix=PREFIX +) + +@app.get("/", response_class= HTMLResponse) +async def hello(request: Request): + return """ + + + Привет + + +

Это API, а не сайт!

+ + + """ + +@router.get('/') +async def get_ageement(id_account: Optional[UUID] = None) -> Sequence[Agreement]: + with db_engine.begin() as con: + query = text("SELECT * FROM agreement WHERE id_account=:id_account").params({"id_account":id_account}) + return con.execute(query).fetchall() + + +@router.delete("/") +async def delete_pk(acc_list: Sequence[UUID]): + with db_engine.begin() as con: + stmt = text("DELETE agreement WHERE id_account IN :acc_list") + params = {"acc_list":acc_list} + stmt = stmt.bindparams(bindparam('acc_list', expanding=True)) + con.execute(stmt, params) + return {"msg":"has deleted"} + + +@router.post("/") +async def add_agreement(agrees: Sequence[AgreementCreate]): + with db_engine.begin() as con: + dict_list=[] + acc_list = [] + for agree in agrees: + agree_dict = agree.model_dump() + dict_list.append(agree_dict) + acc_id = agree_dict.get("id_account") + if acc_id not in acc_list: + acc_list.append(acc_id) + await delete_pk(acc_list) + stmt = insert(Agreement).values(dict_list) + con.execute(stmt) + con.commit() + return {"msg": "added succesfully"} + +app.include_router(router) + +if __name__ == "__main__": + import uvicorn + uvicorn.run( + app, + host=os.getenv("HOST"), + port=int(os.getenv("PORT")) + ) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..432890a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +fastapi +uvicorn +sqlmodel +pyodbc +python-dotenv +orjson \ No newline at end of file