Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 114ea5c

Browse filesBrowse files
committed
updated
1 parent de9b833 commit 114ea5c
Copy full SHA for 114ea5c

File tree

Expand file treeCollapse file tree

5 files changed

+150
-2
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+150
-2
lines changed
+39Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""created_posts_table
2+
3+
Revision ID: 1c7984990e1d
4+
Revises: 15770e820938
5+
Create Date: 2022-07-06 23:15:42.761079
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from sqlalchemy.dialects import postgresql
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '1c7984990e1d'
14+
down_revision = '15770e820938'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade() -> None:
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.create_table('posts',
22+
sa.Column('id', postgresql.UUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False),
23+
sa.Column('user_id', postgresql.UUID(), nullable=False),
24+
sa.Column('title', sa.String(), nullable=False),
25+
sa.Column('content', sa.String(), nullable=False),
26+
sa.Column('category', sa.String(), nullable=False),
27+
sa.Column('image', sa.String(), nullable=False),
28+
sa.Column('created_at', sa.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False),
29+
sa.Column('updated_at', sa.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False),
30+
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
31+
sa.PrimaryKeyConstraint('id')
32+
)
33+
# ### end Alembic commands ###
34+
35+
36+
def downgrade() -> None:
37+
# ### commands auto generated by Alembic - please adjust! ###
38+
op.drop_table('posts')
39+
# ### end Alembic commands ###

‎app/main.py

Copy file name to clipboardExpand all lines: app/main.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from fastapi import FastAPI
22
from fastapi.middleware.cors import CORSMiddleware
33
from app.config import settings
4-
from app.routers import user, auth
4+
from app.routers import user, auth, post
55

66
app = FastAPI()
77

@@ -20,6 +20,7 @@
2020

2121
app.include_router(auth.router, tags=['Auth'], prefix='/api/auth')
2222
app.include_router(user.router, tags=['Users'], prefix='/api/users')
23+
app.include_router(post.router, tags=['Posts'], prefix='/api/posts')
2324

2425

2526
@app.get('/api/healthchecker')

‎app/models.py

Copy file name to clipboardExpand all lines: app/models.py
+20-1Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
from unicodedata import category
12
from uuid import UUID
23
from .database import Base
3-
from sqlalchemy import TIMESTAMP, Column, String, Boolean, text
4+
from sqlalchemy import TIMESTAMP, Column, ForeignKey, String, Boolean, text
45
from sqlalchemy.dialects.postgresql import UUID
6+
from sqlalchemy.orm import relationship
57

68

79
class User(Base):
@@ -18,3 +20,20 @@ class User(Base):
1820
nullable=False, server_default=text("now()"))
1921
updated_at = Column(TIMESTAMP(timezone=True),
2022
nullable=False, server_default=text("now()"))
23+
24+
25+
class Post(Base):
26+
__tablename__ = 'posts'
27+
id = Column(UUID, primary_key=True, nullable=False,
28+
server_default=text("uuid_generate_v4()"))
29+
user_id = Column(UUID, ForeignKey(
30+
'users.id', ondelete='CASCADE'), nullable=False)
31+
title = Column(String, nullable=False)
32+
content = Column(String, nullable=False)
33+
category = Column(String, nullable=False)
34+
image = Column(String, nullable=False)
35+
created_at = Column(TIMESTAMP(timezone=True),
36+
nullable=False, server_default=text("now()"))
37+
updated_at = Column(TIMESTAMP(timezone=True),
38+
nullable=False, server_default=text("now()"))
39+
user = relationship('User')

‎app/routers/post.py

Copy file name to clipboard
+67Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from typing import List
2+
from app import oauth2
3+
from .. import schemas, models
4+
from sqlalchemy.orm import Session
5+
from fastapi import Depends, HTTPException, status, APIRouter, Response
6+
from ..database import get_db
7+
8+
router = APIRouter()
9+
10+
11+
@router.get("/")
12+
def get_posts(db: Session = Depends(get_db), limit: int = 10, page: int = 1, search: str = ''):
13+
skip = (page - 1) * limit
14+
15+
posts = db.query(models.Post).group_by(models.Post.id).filter(
16+
models.Post.title.contains(search)).limit(limit).offset(skip).all()
17+
return {'status': 'success', 'results': len(posts), 'data': posts}
18+
19+
20+
@router.post('/', status_code=status.HTTP_201_CREATED, response_model=schemas.PostResponse)
21+
def create_post(post: schemas.CreatePostSchema, db: Session = Depends(get_db), user_id: str = Depends(oauth2.require_user)):
22+
new_post = models.Post(**post.dict(), user_id=user_id)
23+
db.add(new_post)
24+
db.commit()
25+
db.refresh(new_post)
26+
return new_post
27+
28+
29+
@router.put('/{id}', response_model=schemas.PostResponse)
30+
def update_post(id: str, post: schemas.CreatePostSchema, db: Session = Depends(get_db), user_id: str = Depends(oauth2.require_user)):
31+
post_query = db.query(models.Post).filter(models.Post.id == id)
32+
updated_post = post_query.first()
33+
34+
if not updated_post:
35+
raise HTTPException(status_code=status.HTTP_200_OK,
36+
detail=f'No post with this id: {id} found')
37+
if updated_post.owner_id != user_id:
38+
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
39+
detail='You are not allowed to perform this action')
40+
post_query.update(post.dict(), synchronize_session=False)
41+
db.commit()
42+
return updated_post
43+
44+
45+
@router.get('/{id}', response_model=schemas.PostResponse)
46+
def get_post(id: str, db: Session = Depends(get_db), user_id: str = Depends(oauth2.require_user)):
47+
post = db.query(models.Post).filter(models.Post.id == id).first()
48+
if not post:
49+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
50+
detail=f"No post with this id: {id} found")
51+
return post
52+
53+
54+
@router.delete('/{id}')
55+
def delete_post(id: int, db: Session = Depends(get_db), user_id: str = Depends(oauth2.require_user)):
56+
post_query = db.query(models.Post).filter(models.Post.id == id)
57+
post = post_query.first()
58+
if not post:
59+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
60+
detail=f'No post with this id: {id} found')
61+
62+
if post.owner_id != user_id:
63+
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
64+
detail='You are not allowed to perform this action')
65+
post_query.delete(synchronize_session=False)
66+
db.commit()
67+
return Response(status_code=status.HTTP_204_NO_CONTENT)

‎app/schemas.py

Copy file name to clipboardExpand all lines: app/schemas.py
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,25 @@ class UserResponse(UserBaseSchema):
2727
id: str
2828
created_at: datetime
2929
updated_at: datetime
30+
31+
32+
class PostBaseSchema(BaseModel):
33+
title: str
34+
content: str
35+
category: str
36+
image: str
37+
user_id: str | None = None
38+
39+
class Config:
40+
orm_mode = True
41+
42+
43+
class CreatePostSchema(PostBaseSchema):
44+
pass
45+
46+
47+
class PostResponse(PostBaseSchema):
48+
id: str
49+
user: UserResponse
50+
created_at: datetime
51+
updated_at: datetime

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.