get_query_results works correctly. relationships between models changed

This commit is contained in:
DmitryGantimurov 2023-08-07 22:27:23 +03:00
parent dfe1f90748
commit f15c17a17e
8 changed files with 135 additions and 80 deletions

View File

@ -18,18 +18,18 @@ engine = create_engine(
SessionLocal = sessionmaker(bind=engine, autoflush=True, autocommit=False)
database = SessionLocal()
# Base = declarative_base()
Base = declarative_base()
# add your model's MetaData object here
# for 'autogenerate' support
# in your application's model:
# # add your model's MetaData object here
# # for 'autogenerate' support
# # in your application's model:
class Base(DeclarativeBase):
metadata = MetaData(naming_convention={
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_`%(constraint_name)s`",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
})
# class Base(DeclarativeBase):
# metadata = MetaData(naming_convention={
# "ix": "ix_%(column_0_label)s",
# "uq": "uq_%(table_name)s_%(column_0_name)s",
# "ck": "ck_%(table_name)s_`%(constraint_name)s`",
# "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
# "pk": "pk_%(table_name)s"
# })

View File

@ -7,12 +7,13 @@ from fastapi.templating import Jinja2Templates
from fastapi.requests import Request
from pydantic import json
from typing import Any, Annotated, List
from typing import Any, Annotated, List, Union
from starlette.staticfiles import StaticFiles
import requests
from uuid import uuid4
import random
import datetime
import ast
import pathlib
@ -20,7 +21,8 @@ import shutil
import os
from .db import Base, engine, SessionLocal, database
from .service import add_poems_to_db, generate_poem, check_obsolete
from .service import add_poems_to_db, generate_poem, check_obsolete, get_query_results
from .scheduler import app as app_rocketry
from . import schemas, models, utils
Base.metadata.create_all(bind=engine)
@ -38,17 +40,23 @@ app.mount("/uploads", StaticFiles(directory = "./uploads"))
# add_poems_to_db(database)
@app.get("/api/announcements")#адрес объявлений
def annoncements_list(owner_id: int = None, metro: str = None, category: str = None, booked_by: int = 0):
# Каждый день в 00.00 проверяем все объявления (сравниваем текущую дату и срок годности)
# session_rocketry = app_rocketry.session
@app.get("/api/announcements", response_model=List[schemas.Announcement])#адрес объявлений
def annoncements_list(obsolete: Union[bool, None] = False, user_id: Union[int, None] = None, metro: Union[str, None] = None,
category: Union[str, None] = None):
# Считываем данные из Body и отображаем их на странице.
# В последствии будем вставлять данные в html-форму
params_to_sort = schemas.SortAnnouncements(obsolete=obsolete, user_id=user_id, metro=metro, category=category)
# Фильтруем по сроку годности
not_expired = check_obsolete(current_date=datetime.date.today())
# not_expired = check_obsolete(current_date=datetime.date.today())
# Фильтруем по другим параметрам и делаем пересечение с not_expired
result = not_expired.intersect(get_query_results(params_to_sort))
# result = not_expired.intersect(get_query_results(params_to_sort))
result = get_query_results(db=database, schema=params_to_sort)
return {"Success" : True, "list_of_announcements": result}
return result
@app.get("/api/announcement")#адрес объявления
@ -68,7 +76,7 @@ def single_annoncement(user_id:int):
# Занести объявление в базу данных
@app.put("/api/announcement")#адрес объявлений
def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[int, Form()],
def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[datetime.date, Form()],
address: Annotated[str, Form()], longtitude: Annotated[float, Form()], latitude: Annotated[float, Form()],
description: Annotated[str, Form()], src: UploadFile, metro: Annotated[str, Form()],
trashId: Annotated[int, Form()] = None):
@ -167,12 +175,14 @@ async def read_own_items(
# начисляем баллы пользователю
@app.post("/api/user/rating")
def add_points(data: schemas.AddPoints):
user = utils.get_user(data.user_id)
if not user:
raise HTTPException(status_code=404, detail="Item not found")
user.rating += data.rate
return {"Success": True}
def add_points(data: schemas.AddPoints, current_user: Annotated[schemas.User, Depends(utils.get_current_user)]):
if current_user.id != data.user_id:
user = utils.get_user(data.user_id)
if not user:
raise HTTPException(status_code=404, detail="Item not found")
user.num_of_ratings += 1
user.rating = (user.rating + data.rate)/user.num_of_ratings
return {"Success": True}
# получаем данные о баллах пользователя

View File

@ -24,15 +24,16 @@ class User(Base):#класс пользователя
surname = Column(String)#фамилия пользователя
disabled = Column(Boolean, default=False)
rating = Column(Integer, default=0) #баллы пользователя
num_of_ratings = Column(Integer, default=0) # количество оценок (т.е. то, сколько раз другие пользователи оценили текущего)
reg_date = Column(Date) # дата регистрации
items = relationship("Announcement", back_populates="users")
announcements = relationship("Announcement", back_populates="user")
class Announcement(Base): #класс объявления
__tablename__ = "announcements"
id = Column(Integer, primary_key=True, index=True) # айди объявления
user_id = Column(Integer, ForeignKey("users.id", name="fk_users_id")) # айди создателя объявления
user_id = Column(Integer, ForeignKey("users.id")) # айди создателя объявления
name = Column(String) # название объявления
category = Column(String) #категория продукта из объявления
best_by = Column(Date) #срок годности продукта из объявления
@ -47,7 +48,7 @@ class Announcement(Base): #класс объявления
# state = Column(Enum(State), default=State.published) # состояние объявления (опубликовано, забронировано, устарело)
obsolete = Column(Boolean, default=False) # состояние объявления (по-умолчанию считаем его актуальным)
owner = relationship("User", back_populates="items")
user = relationship("User", back_populates="announcements")
class Trashbox(Base): #класс мусорных баков

13
back/scheduler.py Normal file
View File

@ -0,0 +1,13 @@
from . import service
from rocketry import Rocketry
from rocketry.conds import daily
import datetime
app = Rocketry()
# Create some tasks:
@app.task("daily")
def daily_check():
service.check_obsolete(current_date=datetime.date.today())

View File

@ -26,6 +26,10 @@ class Announcement(BaseModel):
trashId: Union[int, None] = None
booked_by: int #статус бронирования (либо -1, либо айди бронирующего)
class Config:
orm_mode = True
arbitrary_types_allowed=True
class Token(BaseModel):
access_token: str
@ -73,7 +77,7 @@ class DisposeRequest(BaseModel):
trashbox: TrashboxRequest
class SortAnnouncements(BaseModel):
expired: Union[int, None] = False
obsolete: Union[int, None] = False
user_id: Union[int, None] = None
metro: Union[str, None] = None
category: Union[str, None] = None

View File

@ -41,12 +41,12 @@ def add_poems_to_db(db: Session):
f1.close()
# def generate_poem(db: Session):
# # генерируем 1 случайное id и выбираем объект бд с этим id
# rand_id = random.randint(1, 102)
# poem = db.query(models.Poems).filter(models.Poems.id == rand_id).first()
# # возвращаем название и текст стихотворения
# return {"name": poem.title, "text": poem.poem_text, "author":""} # добавить поле author в Poems
def generate_poem(db: Session):
# генерируем 1 случайное id и выбираем объект бд с этим id
rand_id = random.randint(1, 102)
poem = db.query(models.Poems).filter(models.Poems.id == rand_id).first()
# возвращаем название и текст стихотворения
return {"name": poem.title, "text": poem.poem_text, "author":""} # добавить поле author в Poems
#Вова тестирует получение поэм, Димоны, помогите пж
# def poems_to_front(db: Annotated[Session, Depends(utils.get_db)]):
# kolvo_stixov = 109 # пока количество стихотворений = 101
@ -58,7 +58,7 @@ def add_poems_to_db(db: Session):
def get_query_results(db: Annotated[Session, Depends(utils.get_db)], schema: schemas.SortAnnouncements):
def get_query_results(schema: schemas.SortAnnouncements, db: Annotated[Session, Depends(utils.get_db)]):
"""Функция для последовательного применения различных фильтров (через схему SortAnnouncements)"""
res = db.query(models.Announcement)
fields = schema.__dict__ # параметры передоваемой схемы SortAnnouncements (ключи и значения)
@ -71,16 +71,13 @@ def get_query_results(db: Annotated[Session, Depends(utils.get_db)], schema: sch
def check_obsolete(db: Annotated[Session, Depends(utils.get_db)], current_date: datetime.date):
"""
Возвращаем список объектов базы данных типа Announcement
, удовлетворяющих условию obsolete == True
Обновляем поле obsolete у всех объявлений раз в сутки
"""
list_to_return = []
not_obsolete = database.query(models.Announcement).filter(models.Announcement.obsolete == True).all()
for ann in not_obsolete:
announcements = db.query(models.Announcement).all()
for ann in announcements:
if ann.best_by < current_date:
ann.obsolete = False
else:
list_to_return.append(ann)
return list_to_return
ann.obsolete = True

View File

@ -0,0 +1,64 @@
"""User model got a new field: num_of_ratings; delete name of ForeignKey; relationships changed
Revision ID: 9c19b9658512
Revises: 4e4d30fd58fc
Create Date: 2023-08-07 18:16:32.386940
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '9c19b9658512'
down_revision = '4e4d30fd58fc'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('_alembic_tmp_users')
with op.batch_alter_table('announcements', schema=None) as batch_op:
batch_op.add_column(sa.Column('obsolete', sa.Boolean(), nullable=True))
batch_op.drop_column('state')
with op.batch_alter_table('poems', schema=None) as batch_op:
batch_op.add_column(sa.Column('title', sa.String(), nullable=True))
batch_op.add_column(sa.Column('text', sa.String(), nullable=True))
batch_op.add_column(sa.Column('author', sa.String(), nullable=True))
batch_op.drop_column('poem_text')
batch_op.drop_column('poem_name')
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.add_column(sa.Column('num_of_ratings', sa.Integer(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.drop_column('num_of_ratings')
with op.batch_alter_table('poems', schema=None) as batch_op:
batch_op.add_column(sa.Column('poem_name', sa.VARCHAR(), nullable=True))
batch_op.add_column(sa.Column('poem_text', sa.VARCHAR(), nullable=True))
batch_op.drop_column('author')
batch_op.drop_column('text')
batch_op.drop_column('title')
with op.batch_alter_table('announcements', schema=None) as batch_op:
batch_op.add_column(sa.Column('state', sa.VARCHAR(length=9), nullable=True))
batch_op.drop_column('obsolete')
op.create_table('_alembic_tmp_users',
sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('email', sa.VARCHAR(), nullable=True),
sa.Column('hashed_password', sa.VARCHAR(), nullable=True),
sa.Column('name', sa.VARCHAR(), nullable=True),
sa.Column('surname', sa.VARCHAR(), nullable=True),
sa.Column('disabled', sa.BOOLEAN(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###

View File

@ -1,34 +0,0 @@
"""state(enum) -> obsolete(Boolean)
Revision ID: faecbd04e5eb
Revises: 4e4d30fd58fc
Create Date: 2023-08-05 23:57:31.784676
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'faecbd04e5eb'
down_revision = '4e4d30fd58fc'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('announcements', schema=None) as batch_op:
batch_op.add_column(sa.Column('obsolete', sa.Boolean(), nullable=True))
batch_op.drop_column('state')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('announcements', schema=None) as batch_op:
batch_op.add_column(sa.Column('state', sa.VARCHAR(length=9), nullable=True))
batch_op.drop_column('obsolete')
# ### end Alembic commands ###