Articles & Content
CRUD system for managing articles with publish/draft status.
Features
- Create articles with title and content
- Read articles (own + published)
- Update articles (own only)
- Delete articles (own only)
- Publish/Draft status
- Unlimited articles (all tiers)
- Author attribution
Quick Start
Create Article (Frontend)
Visit: http://localhost:5173/dashboard/my-articles
Click "New Article" → Fill form → Save
Create Article (API)
| Bash |
|---|
| curl -X POST http://localhost:8020/api/articles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "My First Article",
"content": "Article content here",
"is_published": true
}'
|
Frontend Usage
List Articles
| TypeScript |
|---|
| import { useArticles } from '@/hooks/api/useArticles';
const MyArticles = () => {
const { data: articles, isLoading } = useArticles();
return (
<div>
{articles?.map(article => (
<ArticleCard key={article.id} article={article} />
))}
</div>
);
};
|
Create Article
| TypeScript |
|---|
| import { useCreateArticle } from '@/hooks/api/useCreateArticle';
const CreateArticle = () => {
const createMutation = useCreateArticle();
const handleSubmit = (data: ArticleCreate) => {
createMutation.mutate(data, {
onSuccess: () => navigate('/dashboard/my-articles')
});
};
return <ArticleForm onSubmit={handleSubmit} />;
};
|
Update Article
| TypeScript |
|---|
| import { useUpdateArticle } from '@/hooks/api/useUpdateArticle';
const EditArticle = ({ id }) => {
const updateMutation = useUpdateArticle(id);
const handleSubmit = (data: ArticleUpdate) => {
updateMutation.mutate(data);
};
return <ArticleForm onSubmit={handleSubmit} />;
};
|
Backend Implementation
Models
| Python |
|---|
| # app/models.py
class Article(UUIDModelBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
title: str
content: str
author: str
published_at: Optional[datetime.datetime]
is_published: bool = Field(default=False)
user_id: uuid.UUID = Field(foreign_key="user.id")
user: "User" = Relationship(back_populates="articles")
|
Service
| Python |
|---|
| # app/services/article_service.py
class ArticleService:
async def create_article(self, article_data: ArticleCreate):
article = Article(
**article_data.model_dump(),
user_id=self.current_user.user_id,
author=self.current_user.email
)
self.db.add(article)
await self.db.commit()
return article
|
Ownership Check
Users can only edit/delete their own articles:
| Python |
|---|
| # Automatic ownership validation
if article.user_id != self.current_user.user_id:
raise HTTPException(403, "Can only edit own articles")
|
API Endpoints
GET /api/articles - List articles
POST /api/articles - Create article
GET /api/articles/{id} - Get single article
PUT /api/articles/{id} - Update article
DELETE /api/articles/{id} - Delete article
Full API reference
Database Schema
| SQL |
|---|
| CREATE TABLE article (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
content TEXT NOT NULL,
author VARCHAR NOT NULL,
published_at TIMESTAMP,
is_published BOOLEAN DEFAULT FALSE,
user_id UUID REFERENCES user(id)
);
|
Common Tasks
Publish Article
| Python |
|---|
| # Update is_published to True
article_data = ArticleUpdate(is_published=True)
await article_service.update_article(article_id, article_data)
|
Filter Published Only
| Python |
|---|
| # Backend
articles = await article_service.get_all_articles(published_only=True)
# Frontend
const { data } = useArticles(true); // published only
|
Files Reference
app/models.py - Article model
app/services/article_service.py - Business logic
app/controllers/article.py - API endpoints
app/schemas/article.py - Request/response models
frontend/src/pages/Article/ - Article pages
frontend/src/hooks/api/useArticles.ts - React hooks