
SmartBlog๋ OpenAI API๋ฅผ ํ์ฉํ AI ๊ธฐ๋ฅ์ด ํ์ฌ๋ Django ๋ธ๋ก๊ทธ ํ๋ซํผ์ ๋๋ค. ์ฌ์ฉ์๊ฐ ๋ ์ฝ๊ณ ํจ์จ์ ์ผ๋ก ๋ธ๋ก๊ทธ๋ฅผ ์์ฑํ ์ ์๋๋ก ๋ค์ํ AI ์ด์์คํดํธ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
smartblog/
โโโ accounts/ # ์ฌ์ฉ์ ๊ด๋ฆฌ ์ฑ
โ โโโ models.py # CustomUser, Follow ๋ชจ๋ธ
โ โโโ views.py # ์ธ์ฆ, ํ๋กํ, ํ๋ก์ฐ ๋ทฐ
โ โโโ admin.py # ๊ด๋ฆฌ์ ์ค์
โโโ blog/ # ๋ธ๋ก๊ทธ ๋ฉ์ธ ์ฑ
โ โโโ models.py # Post, Comment, Like, Tag, AIUsageLog ๋ชจ๋ธ
โ โโโ views.py # ๊ฒ์๊ธ, ๋๊ธ, ์ข์์ ๋ทฐ
โ โโโ ai_views.py # AI ๊ธฐ๋ฅ API ๋ทฐ
โ โโโ ai_service.py # OpenAI API ์๋น์ค ํด๋์ค
โโโ templates/ # HTML ํ
ํ๋ฆฟ
โโโ static/ # CSS, JS, ์ด๋ฏธ์ง ํ์ผ
โโโ media/ # ์ฌ์ฉ์ ์
๋ก๋ ํ์ผ
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
ai_usage_count = models.IntegerField(default=0)
def get_follower_count(self):
return self.followers.count()
def toggle_follow(self, user):
follow, created = Follow.objects.get_or_create(
follower=self, following=user
)
if not created:
follow.delete()
return False, user.get_follower_count()
return True, user.get_follower_count()
ํน์ง:
AbstractUser๋ฅผ ํ์ฅํ์ฌ ์ปค์คํ
ํ๋ ์ถ๊ฐManyToMany ๊ด๊ณ ๊ตฌํai_usage_count ํ๋class OpenAIService:
def __init__(self):
self.client = OpenAI(api_key=settings.OPENAI_API_KEY)
self.model = "gpt-4o-mini"
def generate_title_suggestions(self, content: str, count: int = 5):
messages = [
{
"role": "system",
"content": "ํ๊ตญ์ด ๋ธ๋ก๊ทธ ์ ๋ชฉ์ ์ถ์ฒํ๋ ์ ๋ฌธ๊ฐ์
๋๋ค."
},
{
"role": "user",
"content": f"๋ค์ ๊ธ์ ๋ํ {count}๊ฐ์ ์ ๋ชฉ์ ์ถ์ฒํด์ฃผ์ธ์: {content}"
}
]
response = self._make_request(messages)
return self._parse_titles(response)
ํน์ง:
// ์ข์์ ํ ๊ธ
function toggleLike(postId) {
fetch(`/blog/like/${postId}/`, {
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken'),
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
updateLikeButton(postId, data.is_liked, data.like_count);
showMessage(data.message, 'success');
}
});
}
ํน์ง:
def get_queryset(self):
return Post.objects.select_related("author")\
.prefetch_related("tags", "likes")\
.annotate(likes_count=Count('likes'))\
.order_by("-created_at")
ํน์ง:
select_related: ์ธ๋ํค ๊ด๊ณ ์ต์ ํprefetch_related: ๋ค๋๋ค ๊ด๊ณ ์ต์ ํannotate: ์ง๊ณ ํจ์๋ก ์ข์์ ์ ๊ณ์ฐ๋ฌธ์ : ๋๊ธ์ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ด๋ป๊ฒ ํํํ ๊น?
ํด๊ฒฐ์ฑ :
class Comment(models.Model):
parent = models.ForeignKey("self", on_delete=models.CASCADE,
null=True, blank=True)
๋ฌธ์ : Ajax ์์ฒญ์์ CSRF ํ ํฐ ์๋ฌ ๋ฐ์
ํด๊ฒฐ์ฑ :
function getCookie(name) {
// ์ฟ ํค์์ CSRF ํ ํฐ ์ถ์ถ
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
# 1. ํ๋ก์ ํธ ํด๋ก
git clone <repository-url>
cd smartblog
# 2. ๊ฐ์ํ๊ฒฝ ์์ฑ ๋ฐ ํ์ฑํ
python -m venv venv
Windows: venv\Scripts\activate # MacOS : source venv/bin/activate
# 3. ํจํค์ง ์ค์น
pip install django python-environ openai
# 4. ํ๊ฒฝ๋ณ์ ์ค์ (.env ํ์ผ ์์ฑ)
DEBUG=True
OPENAI_API_KEY=your_openai_api_key_here
DATABASE_URL=sqlite:///db.sqlite3
ALLOWED_HOSTS=127.0.0.1,localhost
# 1. ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ง์ด๊ทธ๋ ์ด์
python manage.py makemigrations
python manage.py migrate
# 2. ์ํผ์ ์ ์์ฑ
python manage.py createsuperuser
# 3. ๊ฐ๋ฐ ์๋ฒ ์คํ
python manage.py runserver
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํตํด Django ํ๋ ์์ํฌ์ ๊ฐ๋ ฅํจ์ ์ค๊ฐํ์ต๋๋ค. ํนํ ORM์ ํธ๋ฆฌํจ๊ณผ MTV ํจํด์ ๋ช ํํ ๊ตฌ์กฐ๊ฐ ๊ฐ๋ฐ ํจ์จ์ฑ์ ํฌ๊ฒ ๋์ฌ์ฃผ์์ต๋๋ค.
OpenAI API๋ฅผ ํ์ฉํ์ฌ ์ค์ ๋ก ์ฌ์ฉ์์๊ฒ ๋์์ด ๋๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ด์ ๋ฟ๋ฏํ์ต๋๋ค.
์์ผ๋ก๋ ์ฌ์ฉ์ ์ค์ฌ์ ์๋น์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ง์์ ์ผ๋ก ํ์ตํ๊ณ ๊ฐ์ ํด๋๊ฐ๊ฒ ์ต๋๋ค!