본문 바로가기

TIl

N:1 2

유저와 게시글, 게시글과 댓글의 연결

User와 다른 모델 간의 모델 관계 설정

  1. User & Article
  2. User & Comment

모델 관계 설정

# articles/models.py
from django.conf import settings

class Article(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

User 모델을 참조하는 2가지 방법

  1. get_user_model()
  2. settings.AUTH_USER_MODEL

django 프로젝트 ‘내부적인 구동 순서’와 ‘반환 값’에 따른 이유

기억할 것은 User 모델은 직접 참조하지 않는다는 것

  get_user_model() settings.AUTH_USER_MODEL
반환 값 User Object (객체) ‘accounts.USER’ (문자열)
사용 위치 models.py가 아닌 다른 모든 위치 models.py가 아닌 다른 모든 위치 models.py

models.py 에서는 문자열로 참조해야된다. 내부적인 구동 순서에 따라서 존재하지 않은 User 객체를 가져올 수 없기 때문에 문자열로 가져오고 나중에 대체된다는 개념

Migration

  1. makemigration
    • 기존에 테이블이 있는 상황에서 필드를 추가 하려하기 때문에 발생하는 과정
    • 기본적으로 모든 필드에는 NOT NULL 제약조건이 있기 때문에 데이터가 없이는 새로운 필드가 추가되지 못함
    • ‘1’을 입력하고 Enter 진행( 다음 화면에서 직접 기본 값 입력)
    • Provide a one-off default now (will be set on all existing rows with a null value for this column)
  2. 추가하는 외래 키 필드에 어떤 데이터를 넣을 것인지 직접 입력해야 함
    • 마찬가지로 1을 입력하고 Enter 진행
    • ⇒ 기존에 작성된 게시글이 있다면 모두 1 번 회원이 작성한 것으로 처리됨
    Please enter the default value as valid Python.
    The datetime and django.utils.timezone modules are available, so it is possible to provide e.g. timezone.now as a value.
    Type 'exit' to exit this prompt
    

게시글 CREATE

  1. 기존 Article 출력 변화 확인 할 시 User 모델에 대한 외래 키 데이터 입력을 받기 위한 불필요한 input이 출력되고있음
  2. 출력 필드 수정
# articles/forms.py

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
       # fields = '__all__'
        fields = ('title','content',)
  1. 게시글 작성 시 에러 발생 = user_id 필드 데이터가 누락되었기 때문
  2. 게시글 작성 시 작성자 정보가 함께 저장될 수 있도록 save의 commit 옵션 활용
# articles/views.py

@login_required
def create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
          # article = form.save()
	          # save() 하기 전에 user 정보를 article.user에다가 넣어줘야 된다.
	          article = form.save(commit=False) 
            article.user = request.user
            article.save()
           
            return redirect('articles:detail', article.pk)

게시글 Read

<!-- articles/index.html -->
<p>작성자 : {{article.user}} <p>

<!-- articles/detail.html -->
<p>작성자 : {{article.user}} <p>

게시글 update

본인의 게시글만 수정 할 수 있도록 하기

  • 게시글 수정 요청 사용자와 게시글 작성 사용자를 비교
# articles/views.py

@login_required
def update(request, pk):
    article = Article.objects.get(pk=pk)
    if request.method == 'POST':
        form = ArticleForm(request.POST, instance=article)
        if form.is_valid():
            form.save()
            return redirect('articles:detail', article.pk)
    else:
        form = ArticleForm(instance=article)

@login_required
def update(request, pk):
    article = Article.objects.get(pk=pk)
    if request.user == article.user: # 작성한 사용자가 아닐 경우
        if request.method == 'POST':
            form = ArticleForm(request.POST, instance=article)
            if form.is_valid():
                form.save()
                return redirect('articles:detail', article.pk)
        else:
            form = ArticleForm(instance=article)
    else:
        return redirect('articles:index') # 메인페이지로 되돌려버려라
  • 해당 게시글 작성자가 아니라면, 수정/삭제 버튼을 출력하지 않도록 하기
<!-- articles/detail.html -->

{% if request.user == article.user %}
  <a href="{% url "articles:update" article.pk %}">UPDATE</a>
  <form action="{% url "articles:delete" article.pk %}" method="POST">
    {% csrf_token %}
    <input type="submit" value="DELETE">
  </form>
  {% endif %}

수정할 때는 인스턴스를 받기 때문에, 생성할 때처럼 save의 commit 옵션 활용을 안해도 된다.

게시글 delete

# articles/views.pt

@login_required
def delete(request, pk):
    article = Article.objects.get(pk=pk)
    # 조건 추가
    if request.user == article.user:
        article.delete()
    return redirect('articles:index')

Comment & User

모델 관계 설정

Comment에도 동일한 과정

댓글 CREATE

게시글 작성 때처럼 user_id 필드 데이터 누락 문제 발생

# articles/views.py

if comment_form.is_valid():
        comment = comment_form.save(commit=False)
        comment.article = article
        comment.user = request.user  # 추가
        comment.save()

댓글 READ

댓글 출력 시 댓글 작성자와 함께 출력

<!-- articles/detail,html -->

{% for comment in comments %}
  <li>
    {{comment.user }} - {{ comment.content }}
    ...
  </li>
{% endfor %}

댓글 DELETE

본인의 댓글만 삭제할 수 있도록 하기

댓글 삭제 요청 사용자와 댓글 작성 사용자를 비교

# articles/views.py

def comments_delete(request, article_pk, comment_pk):
    comment = Comment.objects.get(pk=comment_pk)
    if request.user == comment.user:
        comment.delete()
    return redirect('articles:detail', article_pk)
<!-- articles/detail.html -->

{% if request.user == comment.user %}
		<form action="">
		  <input type="submit" value="삭제">
		</form>
{% endif %}

참고

인증된 사용자만 댓글 작성 및 삭제

# articles/views.py

@login_required
def comments_create(request, pk):
		pass

@login_required
def comments_create(request, article_pk, comment_pk):
		pass

'TIl' 카테고리의 다른 글

Opic 전략  (0) 2025.03.10
REST  (0) 2025.03.10
N:1 1  (1) 2024.04.22
N:M 2  (1) 2024.04.22
N:M 1  (1) 2024.04.22