web-dev/labs/lab-6/app/models.py
2026-03-13 13:14:58 +03:00

125 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from typing import Optional, Union, List
from datetime import datetime
import sqlalchemy as sa
from werkzeug.security import check_password_hash, generate_password_hash
from flask_login import UserMixin
from flask import url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import String, ForeignKey, DateTime, Text, Integer, MetaData
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"
})
db = SQLAlchemy(model_class=Base)
class Category(Base):
__tablename__ = 'categories'
id = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(100))
parent_id: Mapped[Optional[int]] = mapped_column(ForeignKey("categories.id"))
def __repr__(self):
return '<Category %r>' % self.name
class User(Base, UserMixin):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
first_name: Mapped[str] = mapped_column(String(100))
last_name: Mapped[str] = mapped_column(String(100))
middle_name: Mapped[Optional[str]] = mapped_column(String(100))
login: Mapped[str] = mapped_column(String(100), unique=True)
password_hash: Mapped[str] = mapped_column(String(200))
created_at: Mapped[datetime] = mapped_column(default=datetime.now)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@property
def full_name(self):
return ' '.join([self.last_name, self.first_name, self.middle_name or ''])
def __repr__(self):
return '<User %r>' % self.login
class Course(Base):
__tablename__ = 'courses'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100))
short_desc: Mapped[str] = mapped_column(Text)
full_desc: Mapped[str] = mapped_column(Text)
rating_sum: Mapped[int] = mapped_column(default=0)
rating_num: Mapped[int] = mapped_column(default=0)
category_id: Mapped[int] = mapped_column(ForeignKey("categories.id"))
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
background_image_id: Mapped[str] = mapped_column(ForeignKey("images.id"))
created_at: Mapped[datetime] = mapped_column(default=datetime.now)
author: Mapped["User"] = relationship()
category: Mapped["Category"] = relationship(lazy=False)
bg_image: Mapped["Image"] = relationship()
# Связь с отзывами
reviews: Mapped[List["Review"]] = relationship(back_populates='course')
def __repr__(self):
return '<Course %r>' % self.name
@property
def rating(self):
if self.rating_num > 0:
return self.rating_sum / self.rating_num
return 0
class Image(db.Model):
__tablename__ = 'images'
id: Mapped[str] = mapped_column(String(100), primary_key=True)
file_name: Mapped[str] = mapped_column(String(100))
mime_type: Mapped[str] = mapped_column(String(100))
md5_hash: Mapped[str] = mapped_column(String(100), unique=True)
object_id: Mapped[Optional[int]]
object_type: Mapped[Optional[str]] = mapped_column(String(100))
created_at: Mapped[datetime] = mapped_column(default=datetime.now)
def __repr__(self):
return '<Image %r>' % self.file_name
@property
def storage_filename(self):
_, ext = os.path.splitext(self.file_name)
return self.id + ext
@property
def url(self):
return url_for('image', image_id=self.id)
# Модель отзыва
class Review(Base):
__tablename__ = 'reviews'
id: Mapped[int] = mapped_column(Integer, primary_key=True)
rating: Mapped[int] = mapped_column(Integer, nullable=False)
text: Mapped[str] = mapped_column(Text, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
course_id: Mapped[int] = mapped_column(ForeignKey('courses.id'))
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
# Связи с курсом и пользователем
course: Mapped['Course'] = relationship(back_populates='reviews')
user: Mapped['User'] = relationship()