Chapter3_Assignment_250123.zip
0.60MB
목록
- User 앱
- 사용자 모델 구현
- 회원가입, 로그인, 로그아웃 기능 구현
- 회원가입
- 로그인
- 로그아웃
- 사용자 프로필 페이지 구현
- Post 앱 (CRUD)
- Post 모델 구현
- 게시판 기능
- 게시글 목록 보기 (Read - List)
- 게시글 상세 보기 (Read - Detail)
- 게시글 작성 기능 (Create)
- 게시글 수정 기능 (Update)
- 게시글 삭제 기능 (Delete)
필수앱 구현
1. View (함수 or 클래스 택 1)
2. 기본 템플릿 (base.html, navbar.html, foodter.html)
3. 데이터베이스 (SQLite3)
평가 기준
- 코드 구조 및 가독성
- MTV 패턴 준수
- 기능의 정확성
- 에러 처리
- 코드 재사용성
- DRF 구현 시 RESTful API 설계 원칙 준수
2. Post 앱 (CRUD)
2.1. Post 모델 구현
필드: 제목, 내용, 작성자, 작성일, 수정일
더보기


from django.db import models
from django.conf import settings
# 글 작성하는 모델
class Article(models.Model):
title = models.CharField(max_length=50) # 제목은 CharField로, 길이는 50자까지
content = models.TextField() # 내용은 TextField로, 아무런 제한 없이 마음껏
created_at = models.DateTimeField(auto_now_add=True) # 생성일은 자동으로 채워지게끔
updated_at = models.DateTimeField(auto_now=True) # 수정일도 자동으로 채워지게끔
author = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="post")
- # author는 models.ForeignKey로 데려와용
- # settings.AUTH_USER_MODEL : settings에 정의해놓은 User 모델을 써용
- # on_delete=models.CASCADE : 연결된 객체(User)가 삭제되면, 참고하고 있는 객체(Post)도 삭제돼용
- # related_name :외래 키로 연결된 모델에서 역으로 참조할 때 사용할 이름을 post로 할 거예용
- ## 예를 들면, User 모델에서 작성한 모든 Post 객체를 가져오고 싶으면 user.post.all()처럼 사용할 수 있어용
2.2. 게시판 기능
2.2.1. 게시글 목록 보기 (post_list)
2.2.1.1. urls.py 추가하기
더보기


from django.urls import path
from . import views
app_name = "post"
urlpatterns = [
path('post-list/', views.post_list, name="post_list"), # 게시글 목록
2.2.1.2. views.py 추가하기
더보기


from django.contrib.auth.decorators import login_required
from .models import Article
# 게시글 목록 보기
# @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
@login_required(login_url="user:login")
def post_list(request):
post_list = Article.objects.all().order_by("-created_at") # 글 목록을 최신순으로 보여줌
context = {"post_list":post_list}
return render(request, "post/post_list.html", context) # post_list.html 양식으로 보여줄게용
- @login_required(login_url="user:login")
- 로그인을 요구하는데, 로그인하지 않았으면 로그인창으로 보내버려요
- post_list = Article.objects.all().order_by("-created_at")
- Article 모델에 있는 항목들을 전부 값으로 불러올 거고, 생성일은 최신순으로 정렬해요
2.2.1.3. post_list.html 추가하기
더보기


<!--게시글 목록 보기-->
{% extends "base.html" %}
{% block content %}
<h1><center>Post List</center></h1>
<!--새 게시물 작성 버튼과 인덱스로 돌아가는 버튼-->
<a href="{% url 'post:post_create' %}"><button>Writing a new post</button></a>
<a href="{% url 'index' %}"><button>Back to index</button></a>
<hr>
<!--Article 모델 로직을 토대로, 글 번호, 제목, 작성자, 추가일, 수정일을 for문으로 돌림-->
<!--최신순으로 정렬됨 ".order_by("-created_at")"-->
{% for post in post_list %}
<a href="{% url 'post:post_detail' post.id%}">
<h3>[{{ post.id }}] {{ post.title}} </h3>
<p>Writer : {{ post.author.username }}</p>
<p>Date of creation_{{ post.created_at }}</p>
<p>Date of revision_{{ post.updated_at }}</p>
<hr>
{% endfor %}
{% endblock content %}
2.2.2. 게시글 상세 보기 (post_detail)
2.2.2.1. urls.py 추가하기
더보기


path('<int:id>/', views.post_detail, name="post_detail"), # 게시글 상세 보기
2.2.2.2. views.py 추가하기
더보기


# 게시글 상세 보기
# @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
@login_required(login_url="user:login")
def post_detail(request, id):
# ⬇️ Article 모델에 있는 id를 조회해용, 조건에 맞는 객체가 없으면 Http404 페이지 보여줘용
post = get_object_or_404(Article, id=id)
context = {"post":post,}
return render(request, "post/post_detail.html", context) # post_detail.html 양식으로 보여줄게용
- # @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
- # ⬇️ Article 모델에 있는 id를 조회해용, 조건에 맞는 객체가 없으면 Http404 페이지 보여줘용
2.2.2.3. post_detail.html 추가하기
더보기


<!--게시글 상세 보기-->
{% extends "base.html" %}
{% block content %}
<h2>Post Detail</h2>
<!--제목-->
<h3>{{ post.title }}</h3>
<!--내용-->
<p>{{ post.content }}</p>
<!--작성자 이름-->
<p>{{ post.author.username }}</p>
<!--최초 작성일-->
<p>{{ post.created_at}}</p>
<!--게시글 삭제하기 버튼-->
<a href="{% url 'post:post_delete' post.id %}"><button>Delete Post</button></a>
<!--게시글 수정하기 버튼-->
<a href="{% url 'post:post_update' post.id %}"><button>Edit Post</button></a>
<!--인덱스로 가는 버튼-->
<a href="{% url 'index'%}"><button>Back to Index</button></a>
<hr>
{% endblock content %}
2.2.3. 게시글 작성 기능 (post_create)
2.2.3.1. urls.py 추가하기
더보기


path('post-create/', views.post_create, name="post_create"), # 게시글 작성하기
2.2.3.2. views.py 추가하기
더보기


from .forms import ArticleForm
# 게시글 작성
# @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
@login_required(login_url="user:login")
def post_create(request):
if request.method == "POST":
# ⬇️ request.POST은 클라이언트가 보낸 POST 요청 데이터, request.FILES은 파일 데이터를 답고 있는 객체
# form에서 request.FILES : FileFiedl나 ImageField가 있으면 반드시 기입!!
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False) # commit=False : 자동 저장 잠만 멈춰봐!
post.author = request.user # 작성자도 기입해줄 거야!! 작성자는 user야
post.save()
return redirect("post:post_detail", post.id)
# GET 요청 데이터면, ArticleForm 형태만 보여줄게용
else:
form = ArticleForm()
context = {"form":form}
return render(request, "post/post_create.html", context) # post_create.html 양식으로 보여줄게용
- # @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
- # ⬇️ request.POST은 클라이언트가 보낸 POST 요청 데이터, request.FILES은 파일 데이터를 답고 있는 객체
- # form에서 request.FILES : FileFiedl나 ImageField가 있으면 반드시 기입!!
- # commit=False : 자동 저장 잠만 멈춰봐!
- # 작성자도 기입해줄 거야!! 작성자는 user야
- # GET 요청 데이터면, ArticleForm 형태만 보여줄게용
2.2.3.3. forms.html 추가하기
더보기


from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article # 모델은 Article
fields = "__all__" # fields에 있는 모든 것들을 쓸 거야
exclude = ("author",) # 작성자는 항목에서 보이지 않도록 제외
2.2.3.4. post_create.html 추가하기
더보기


<!--새로운 글 작성-->
{% extends "base.html" %}
{% block content %}
<h1>New Post</h1>
<!--post_create 로직대로 작동할게용-->
<form action="{% url 'post:post_create'%}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button><br><br>
</form>
<!--post_list로 가버리는 주소-->
<a href='{% url "post:post_list" %}'><button>Go to post list</button></a>
{% endblock content %}
2.2.4. 게시글 수정 기능(post_update)
2.2.4.1. urls.py 추가하기
더보기


path('<int:id>/update/', views.post_update, name="post_update"), # 게시글 수정하기
2.2.4.2. views.py 추가하기
더보기


# 게시글 수정하기
# @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
# @require_http_methods(["GET", "POST"]) : GET과 POST일 때만 작동하도록 코드 보호
@login_required(login_url="user:login")
@require_http_methods(["GET", "POST"])
def post_update(request, id):
post = get_object_or_404(Article, id=id) # Article 모델에 있는 id 조건에 맞는 객체 불러올게용, 없으면 404 error
form = ArticleForm(request.POST, instance=post) # instance : form은 post 내용으로 채울 거예용
if request.user != post.author:
return redirect('post:post_list') # user와 author가 다르면 post_list로 돌아가세욧!
if form.is_valid(): # 값이 유효하다면,
post = form.save() # 저장하세욧
return redirect("post:post_detail", post.id)
else: # 유효하지 않다면,
form = ArticleForm(instance=post) # GET일 때도, form이 post로 채워진 걸 보여줘용
context = {
"post":post,
"form":form}
return render(request, "post/post_update.html", context)
- # @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세
- # @require_http_methods(["GET", "POST"]) : GET과 POST일 때만 작동하도록 코드 보
- # Article 모델에 있는 id 조건에 맞는 객체 불러올게용, 없으면 404 erro
- # instance : form은 post 내용으로 채울 거예
- # user와 author가 다르면 post_list로 돌아가세욧
- # GET일 때도, form이 post로 채워진 걸 보여줘용
2.2.4.3. post_update.html 추가하기
더보기


<!--게시글 수정하기-->
{% extends "base.html" %}
{% block content %}
<h1>Edit Post</h1>
<!--post_update의 로직에 맞춰서 수정하도록 했어용-->
<form action="{% url 'post:post_update' post.id %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Edit Post</button>
</form>
<!--수정하기를 취소하는 버튼이에용-->
<a href="{% url 'post:post_detail' post.id %}"><button>Cancle</button></a>
{% endblock content %}
2.2.5. 게시글 삭제 기능(post_delete)
2.2.5.1. urls.py 추가하기
더보기


path('<int:id>/delete/', views.post_confirm_delete, name="post_delete"), # 게시글 삭제하기
]
2.2.5.2. views.py 추가하기
더보기


# 게시글 삭제하기
# @login_required(login_url="user:login") : 로그인 안 됐으면 login_url로 가세욧
@login_required(login_url="user:login")
def post_confirm_delete(request, id):
post = get_object_or_404(Article, id=id)
if request.user != post.author: # 글 작성자가 아니라면,
return redirect("post:post_list") # post_list로 가세욧
if request.method == "POST":
post.delete()
return redirect("post:post_list")
context = {"post":post}
return render(request,'post/post_confirm_delete.html', context)
2.2.5.3. post_confirm_delete.html 추가하기
더보기





<!--게시글 삭제할 때 보여지는 화면-->
{% extends "base.html" %}
{% block content %}
<!--진짜로 게시글 삭제할 거야?-->
<h1> Are you serious delete this post?</h1>
<!--삭제할 게시글 제목과 내용-->
<div>
<p>Title : {{ post.title }}</p>
<p>Content : {{ post.content }}</p>
</div>
<hr>
<!--post_delete의 로직으로 진행해요-->
<form action="{% url 'post:post_delete' post.id %}" method="POST">
{% csrf_token %}
<button type="submit">Yes, Delete</button>
</form>
<!--글 삭제 취소할게용-->
<a href="{% url 'post:post_list'%}"><button>Cancle</button></a>
{% endblock content %}



'📄 과제' 카테고리의 다른 글
[LLM 필수 과제 1] OpenAI로 나만의 챗봇 만들기 (0) | 2025.01.24 |
---|---|
[Django] Django 개인 과제, User 앱 (0) | 2025.01.20 |
[머신러닝_비지도 학습] 고객 세분화 분석 (0) | 2024.12.30 |
[머신러닝_지도학습] 주택 가격 예측 (0) | 2024.12.23 |