147 lines
5.4 KiB
Python
147 lines
5.4 KiB
Python
import sqlite3
|
|
from dataclasses import dataclass
|
|
from typing import Optional, List
|
|
|
|
@dataclass
|
|
class ArticleModel:
|
|
id: Optional[int] = None
|
|
title: Optional[str] = None
|
|
content: Optional[str] = None
|
|
author_id: Optional[int] = None
|
|
author_name: Optional[str] = None # To hold joint first_name + last_name
|
|
created_at: Optional[str] = None
|
|
|
|
class Articles:
|
|
def __init__(self, db_path="instance/app_database.db"):
|
|
self.db_path = db_path
|
|
self._create_articles_table()
|
|
|
|
def _create_articles_table(self):
|
|
with sqlite3.connect(self.db_path) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS articles (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
author_id INTEGER NOT NULL,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (author_id) REFERENCES users (id)
|
|
);
|
|
"""
|
|
)
|
|
conn.commit()
|
|
|
|
def add_article(self, title: str, content: str, author_id: int) -> Optional[int]:
|
|
"""Insert a new article and return its ID."""
|
|
try:
|
|
with sqlite3.connect(self.db_path) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
"""
|
|
INSERT INTO articles (title, content, author_id)
|
|
VALUES (?, ?, ?)
|
|
""",
|
|
(title, content, author_id),
|
|
)
|
|
conn.commit()
|
|
return cursor.lastrowid
|
|
except sqlite3.Error as e:
|
|
print(f"Error adding article: {e}")
|
|
return None
|
|
|
|
def get_article(self, article_id: int) -> Optional[ArticleModel]:
|
|
"""Fetch a single article by ID, joining users to get the author's name."""
|
|
try:
|
|
with sqlite3.connect(self.db_path) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
"""
|
|
SELECT a.id, a.title, a.content, a.author_id, u.first_name, u.last_name, a.created_at
|
|
FROM articles a
|
|
JOIN users u ON a.author_id = u.id
|
|
WHERE a.id = ?
|
|
""",
|
|
(article_id,),
|
|
)
|
|
row = cursor.fetchone()
|
|
if not row:
|
|
return None
|
|
|
|
author_name = f"{row[4] or ''} {row[5] or ''}".strip() or "Autor necunoscut"
|
|
return ArticleModel(
|
|
id=row[0],
|
|
title=row[1],
|
|
content=row[2],
|
|
author_id=row[3],
|
|
author_name=author_name,
|
|
created_at=row[6],
|
|
)
|
|
except sqlite3.Error as e:
|
|
print(f"Error getting article: {e}")
|
|
return None
|
|
|
|
def get_all_articles(self) -> List[ArticleModel]:
|
|
"""Fetch all articles ordered by created_at DESC (newest first)."""
|
|
try:
|
|
with sqlite3.connect(self.db_path) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
"""
|
|
SELECT a.id, a.title, a.content, a.author_id, u.first_name, u.last_name, a.created_at
|
|
FROM articles a
|
|
JOIN users u ON a.author_id = u.id
|
|
ORDER BY a.created_at DESC
|
|
"""
|
|
)
|
|
rows = cursor.fetchall()
|
|
articles = []
|
|
for row in rows:
|
|
author_name = f"{row[4] or ''} {row[5] or ''}".strip() or "Autor necunoscut"
|
|
articles.append(
|
|
ArticleModel(
|
|
id=row[0],
|
|
title=row[1],
|
|
content=row[2],
|
|
author_id=row[3],
|
|
author_name=author_name,
|
|
created_at=row[6],
|
|
)
|
|
)
|
|
return articles
|
|
except sqlite3.Error as e:
|
|
print(f"Error fetching all articles: {e}")
|
|
return []
|
|
|
|
def update_article(self, article_id: int, title: str, content: str) -> bool:
|
|
"""Update the title and content of an article."""
|
|
try:
|
|
with sqlite3.connect(self.db_path) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
"""
|
|
UPDATE articles
|
|
SET title = ?, content = ?
|
|
WHERE id = ?
|
|
""",
|
|
(title, content, article_id),
|
|
)
|
|
conn.commit()
|
|
return cursor.rowcount > 0
|
|
except sqlite3.Error as e:
|
|
print(f"Error updating article: {e}")
|
|
return False
|
|
|
|
def delete_article(self, article_id: int) -> bool:
|
|
"""Delete an article by ID."""
|
|
try:
|
|
with sqlite3.connect(self.db_path) as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM articles WHERE id = ?", (article_id,))
|
|
conn.commit()
|
|
return cursor.rowcount > 0
|
|
except sqlite3.Error as e:
|
|
print(f"Error deleting article: {e}")
|
|
return False
|