AhmadYarAI commited on
Commit
090db99
·
1 Parent(s): 9ad2816

Post table create

Browse files
Files changed (1) hide show
  1. main.py +84 -10
main.py CHANGED
@@ -4,26 +4,33 @@ from sqlalchemy import create_engine, Column, Integer, String
4
  from sqlalchemy.orm import sessionmaker, declarative_base, Session
5
  import bcrypt
6
  from starlette.middleware.cors import CORSMiddleware
 
 
 
7
 
 
 
 
 
 
8
 
9
  # ----------------- MySQL Connection -----------------
10
  DATABASE_URL = "postgresql+psycopg2://city_university_db_user:au84DXp5L55SYrir23DzrezulwqSJZzc@dpg-d2gitojuibrs73ed7s00-a.oregon-postgres.render.com:5432/city_university_db"
11
  engine = create_engine(DATABASE_URL, pool_pre_ping=True)
12
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
13
- Base = declarative_base()
14
-
15
-
16
  # ----------------- ORM Model (matches user_accounts table) -----------------
17
- class UserDB(Base):
18
- __tablename__ = "user_accounts"
19
- id = Column(Integer, primary_key=True, index=True)
20
- full_name = Column(String(100), nullable=False)
21
- email = Column(String(100), unique=True, index=True, nullable=False)
22
- password = Column(String(255), nullable=False)
23
 
24
 
25
  app = FastAPI()
26
 
 
 
 
 
 
 
 
 
27
  app.add_middleware(
28
  CORSMiddleware,
29
  allow_origins=["*"], # allow all origins
@@ -32,6 +39,14 @@ app.add_middleware(
32
  allow_headers=["*"], # Authorization, Content-Type, etc.
33
  )
34
 
 
 
 
 
 
 
 
 
35
  # Dependency for getting DB session in routes
36
  def get_db():
37
  db = SessionLocal()
@@ -54,6 +69,27 @@ class ResetPassword(BaseModel):
54
  email: EmailStr
55
  new_password: str
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  @app.get("/")
59
  def home():
@@ -94,4 +130,42 @@ def forgot_password(reset: ResetPassword, db: Session = Depends(get_db)):
94
  hashed_pw = bcrypt.hashpw(reset.new_password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
95
  db_user.password = hashed_pw
96
  db.commit()
97
- return {"message": "Password updated successfully"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from sqlalchemy.orm import sessionmaker, declarative_base, Session
5
  import bcrypt
6
  from starlette.middleware.cors import CORSMiddleware
7
+ from sqlalchemy import ForeignKey, DateTime, Text
8
+ from sqlalchemy.orm import relationship
9
+ from datetime import datetime
10
 
11
+ import os, uuid
12
+ from typing import Optional, List
13
+ from fastapi import File, UploadFile, Form
14
+ from starlette.staticfiles import StaticFiles
15
+ from pydantic import BaseModel as PModel
16
 
17
  # ----------------- MySQL Connection -----------------
18
  DATABASE_URL = "postgresql+psycopg2://city_university_db_user:au84DXp5L55SYrir23DzrezulwqSJZzc@dpg-d2gitojuibrs73ed7s00-a.oregon-postgres.render.com:5432/city_university_db"
19
  engine = create_engine(DATABASE_URL, pool_pre_ping=True)
20
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
 
 
 
21
  # ----------------- ORM Model (matches user_accounts table) -----------------
 
 
 
 
 
 
22
 
23
 
24
  app = FastAPI()
25
 
26
+
27
+
28
+ Base = declarative_base()
29
+ UPLOAD_DIR = "uploads"
30
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
31
+ app.mount("/uploads", StaticFiles(directory=UPLOAD_DIR), name="uploads")
32
+
33
+
34
  app.add_middleware(
35
  CORSMiddleware,
36
  allow_origins=["*"], # allow all origins
 
39
  allow_headers=["*"], # Authorization, Content-Type, etc.
40
  )
41
 
42
+
43
+ class UserDB(Base):
44
+ __tablename__ = "user_accounts"
45
+ id = Column(Integer, primary_key=True, index=True)
46
+ full_name = Column(String(100), nullable=False)
47
+ email = Column(String(100), unique=True, index=True, nullable=False)
48
+ password = Column(String(255), nullable=False)
49
+
50
  # Dependency for getting DB session in routes
51
  def get_db():
52
  db = SessionLocal()
 
69
  email: EmailStr
70
  new_password: str
71
 
72
+ class PostOut(PModel):
73
+ id: int
74
+ user_id: int
75
+ content: Optional[str] = None
76
+ image_url: Optional[str] = None
77
+ created_at: datetime
78
+ class Config:
79
+ from_attributes = True # pydantic v2
80
+
81
+
82
+ class PostDB(Base):
83
+ __tablename__ = "posts"
84
+ id = Column(Integer, primary_key=True, index=True)
85
+ user_id = Column(Integer, ForeignKey("user_accounts.id", ondelete="CASCADE"), nullable=False)
86
+ content = Column(Text, nullable=True) # text body (optional)
87
+ image_url = Column(String(300), nullable=True) # store public URL or /uploads/<file>
88
+ created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
89
+
90
+ user = relationship("UserDB") # optional convenience
91
+
92
+
93
 
94
  @app.get("/")
95
  def home():
 
130
  hashed_pw = bcrypt.hashpw(reset.new_password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
131
  db_user.password = hashed_pw
132
  db.commit()
133
+ return {"message": "Password updated successfully"}
134
+
135
+ @app.post("/posts", response_model=PostOut)
136
+ async def create_post(
137
+ user_id: int = Form(...),
138
+ content: Optional[str] = Form(None),
139
+ image: Optional[UploadFile] = File(None),
140
+ db: Session = Depends(get_db),
141
+ ):
142
+ # require at least one of content or image
143
+ if (not content or not content.strip()) and image is None:
144
+ raise HTTPException(status_code=400, detail="Provide content or an image")
145
+
146
+ # verify user exists
147
+ user = db.get(UserDB, user_id)
148
+ if not user:
149
+ raise HTTPException(status_code=404, detail="User not found")
150
+
151
+ image_url = None
152
+ if image is not None:
153
+ allowed = {"image/png", "image/jpeg", "image/jpg", "image/webp"}
154
+ if image.content_type not in allowed:
155
+ raise HTTPException(status_code=415, detail="Unsupported image type")
156
+ ext = { "image/png": ".png", "image/jpeg": ".jpg", "image/jpg": ".jpg", "image/webp": ".webp" }[image.content_type]
157
+ filename = f"{uuid.uuid4().hex}{ext}"
158
+ path = os.path.join(UPLOAD_DIR, filename)
159
+ with open(path, "wb") as f:
160
+ f.write(await image.read())
161
+ image_url = f"/uploads/{filename}" # public via static mount
162
+
163
+ post = PostDB(user_id=user_id, content=content, image_url=image_url)
164
+ db.add(post); db.commit(); db.refresh(post)
165
+ return post
166
+
167
+
168
+ @app.get("/posts", response_model=List[PostOut])
169
+ def list_posts(limit: int = 20, db: Session = Depends(get_db)):
170
+ return db.query(PostDB).order_by(PostDB.created_at.desc()).limit(limit).all()
171
+