[DB] Many to one relationships 2

Jingi·2024년 4월 5일

Web

목록 보기
18/40
post-thumbnail

Many to one raltionships 2

관계 설정

  • User & Article
  • User & Comment

Article(N) - User(1)

  • 0개 이상의 게시글은 1명의 회원에 의해 작성 될 수 있다.

Comment(N) - User(1)

  • 0개 이상의 댓글은 1명의 회원에 의해 작성 될 수 있다.

Article & User

모델 관계 설정

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

class Article(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=10)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

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

  • get_user_model()

  • settings.AUTH_USER_MODEL

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

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

      get_user_model()settings.AUTH_USER_MODEL
      User Objectaccounts.User
      models.py가 아닌 다른 모든 위치models.py

Migration

  • 기존에 테이블이 있는 상황에서 필드를 추가 하려하기 때문에 발생하는 과정
  • 기본적으로 모든 필드에는 NOT NULL 제약 조건이 있기 때문에 데이터가 없이는 새로운 필드가 추가 되지 못함
  • 외래 키 필드에 어떤 데이터를 넣을 것인지 직접 입력해야함

게시글 Create

  • 기존 ArticleForm 출력 변화 확인

  • User 모델에 대한 외래 키 데이터 입력을 받기 위해 불필요한 input이 출력

    # articles/forms.py
    
    from django import forms
    from .models import Article, Comment
    
    class ArticleForm(forms.ModelForm):
        class Meta:
            model = Article
            fields = ('title', 'content',)
            exclude = ('user',)
  • 게시글 작성시 에러 발생

  • user_id 필드 데이터가 누락되었기 때문

    # articles/views.py
    @login_required
    def create(request):
        if request.method == 'POST':
            form = ArticleForm(request.POST)
            if form.is_valid():
                article = form.save(commit=False)
                article.user = request.user
                article.save()
                return redirect('articles:detail', article.pk)
        else:
            form = ArticleForm()
        context = {
            'form': form,
        }
        return render(request, 'articles/create.html', context)
  • 게시글 작성 시 작성자 정보가 함께 저장될 수 있도록 save의 commit 옵션 활용

게시글 Read

  • 각 게시글의 작성자 이름 출력
  • <p>작성자 : {{ article.user }} </p>

게시글 Update

  • 본인의 게시글만 수정 할 수 있도록 하기
    • 게시글 수정 요청 사용자와 게시글 작성 사용자를 비교
      # articles/views.py
      @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')
          context = {
              'form': form,
              'article': article,
          }
          return render(request, 'articles/update.html', context)
  • 해당 게시글의 작성자가 아니라면, 수정/삭제 버튼을 출력하지 않도록 하기
  • {% if request.user == article.uesr %}
            {% if request.user == comment.user %}
            <form action="{% url "articles:comments_delete" article.pk comment.pk %}" method="POST" style="display: inline;">
                {% csrf_token %}
                <input type="submit" value="삭제">
            </form>
            {% endif %}

게시글 DELETE

  • 본인의 게시글만 삭제 할 수 있도록 하기

    • 삭제를 요청하려는 사용자와 게시글을 작성한 사용자를 비교

      # articles/views.py
      
      @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

모델 관계 설정

```python
class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

```

Migration

  • 이전에 Article 와 User 모델 관계 설정 떄와 동일한 상황
  • 기존 Comment 테이블에 새로운 필드가 빈 값으로 추가 될 수 없기 때문에 기본 값 설정 과정이 필요

댓글 Create

  • 댓글 작성 시 이전에 게시글 작성 할 때와 동일한 에러 발생

  • 댓글의 user_id 필드 데이터가 누락되었기 때문

    @login_required
    def comments_create(request, pk):
        article = Article.objects.get(pk=pk)
        comments = article.comment_set.all()
        comment_form = CommentForm(request.POST)
        if comment_form.is_valid():
            comment = comment_form.save(commit=False)
            comment.article = article
            comment.user = request.user
            comment.save()
            return redirect('articles:detail', article.pk)
        context = {
            'comment_form': comment_form,
            'article': article,
            'comments': comments,
        }
        return render(request, 'articles/detail.html', context)
    
  • comment.user = request.user

댓글 READ

  • 댓글 출력 시 댓 글 작성자와 함께 출력
  • {{ comment.user }} - {{ commnet.content }}

댓글 DELETE

  • 본인의 댓글만 삭제 할 수 있도록 하기
    • 댓글 삭제 요청 사용자와 댓글 작성 사용자를 비교
# articles/views.py
@login_required
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)
  • 해당 댓글의 작성자가 아니라면, 댓글 삭제 버튼을 출력하지 않도록 함
    • if request.user == comment.user
{% if request.user == comment.user %}
    <form action="{% url "articles:comments_delete" article.pk comment.pk %}" method="POST" style="display: inline;">
    {% csrf_token %}
    <input type="submit" value="삭제">
    </form>
{% endif %}

참고

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

  • @login_required
profile
데이터 분석에서 백엔드까지...

0개의 댓글