일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 리그오브레전드
- 프로그래머스
- SQL
- greedy
- git
- Riot
- 그리디알고리즘
- github
- sort
- drf
- 장고
- 스파르타내일배움캠프TIL
- 롤
- python
- lol
- 탐욕알고리즘
- 내일배움캠프
- 코딩테스트준비
- 파이썬
- java
- 알고리즘
- API
- 백준
- 코딩테스트
- programmers
- Django
- 라이엇
- 그리디
- 스파르타내일배움캠프
- 자바
- Today
- Total
Lina's Toolbox
Django Model Relationship (1:N) 본문
Many to one relationships
굉장히 흔히 사용되는 관계
1:N 관계 예시
- 만약 Article에 Author라는 개념을 둔다면,
- 하나의 Article은 한 명의 Author를 가질 수 있습니다.
- 한 명의 Author는 여러개의 Article을 가질 수 있습니다.
- 만약 Article에 Comment라는 개념을 둔다면,
- 하나의 Article은 여러개의 Comment를 가질 수 있습니다.
- 하나의 Comment는 하나의 Article을 가질 수 있습니다.
Foreign Key
- 외래키를 의미합니다.
- 관계형 데이터베이스에서 한 테이블(A)의 필드 중 다른 테이블(B)의 행을 유일하게 식별이 가능한 키입니다.
- 테이블(A)에 설정되는 Foreign Key가 반드시 다른 테이블(B)의 Primary Key일 필요는 없으나 유일하게 식별이 가능해야합니다.
이렇게 many to one 관계로 모델링 해보자!
실습 - 댓글 구현하기
댓글(Comment) 구현
- articles/models.py
models.ForeignKey(<참조하는 모델 클래스>, on_delete=<옵션>)
📌 on_delete 옵션
게시글이 삭제되면, 댓글도 같이 삭제해줄 지 결정하는 옵션
✔️ 공식문서 참조 https://docs.djangoproject.com/en/4.2/ref/models/fields/#django.db.models.ForeignKey.on_delete
CASCADE
부모가 삭제되면 이를 참조하는 객체도 같이 삭제
PROTECT
참조하는 객체가 있을경우 예외를 발생시켜 삭제를 못하게함
SET_NULL
참조하는 객체가 삭제될 경우, comment의 게시글 id를 NULL 값으로 바꿔줌
📌 <fieldname>_id
- 참조 테이블의 이름뒤에 _id 를 붙여 컬럼을 자동으로 생성합니다.
ORM 사용해보기
터미널에서 shell_plus 이용하기
→ 터미널에서 아래의 코드를 입력합니다.
python manage.py shell_plus
comment = Comment()
comment.content = “first comment”
comment.save()
1. Comment 생성하기
⇒ article_id 값을 지정하지 않았기때문에 그렇습니다!
⇒ comment.article_id = article.pk로 명시하지 않아도 됩니다!
내부적으로 장고의 ORM이 join을 수행하지만, 우리는 할 필요없이 이렇게 바로 접근 가능하다!!!
짱편한데?
실습 - 두번째 댓글 생성하기
위와 같은 article에 대해 생성해 주세요!
2. comment → article 접근
만약 comment에서 어떤 article인지 접근하고 싶다면 어떻게 할까요?
그렇다면 이 comment가 작성된 article의 title , content 를 알고 싶다면 어떻게 할까요?
- 정참조 = 정방향참조 (comment에서 article을 참조하는것)
- Comment(N) → Article(1) 참조 == 정참조
- 내 Model Class에서 Field가 정의되어 있으므로( Comment는 항상 하나의 참조하는 Article이 있으므로) comment.article 로 아주 쉽게 접근이 가능합니다. 👍
3. article → comments 접근
🤔 만약 article에서 작성된 모든 comment를 알고싶다면?
article.???????
Article 모델 클래스에는 Comment에 대한 어떠한 정보도 없어요!
- 역참조 = 역방향 참조
- Article(1) → Comment(N) 참조 == 역참조
- Django는 역참조의 경우 참조하는 클래스명에 _set 을 붙인 manager를 생성합니다.
그런데 manager 이름이 맘에들지 않는데요?!
→ article.commnets.all() 이렇게 쓰고 싶어요!
→ 수정시 migration 필요
댓글 생성
forms.py
...
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = "__all__"
articles/views.py
articles/templates/articles/article_detail.html
article을 제외하려면
forms.py (2차)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = "__all__"
exclude = ("article",)
로직구현
- articles/urls.py
path("<int:pk>/comments/", views.comments_create, name="comments_create"),
articles/views.py
@require_POST
def comment_create(request, pk):
article = get_object_or_404(Article, pk=pk)
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.article = article
comment.save()
return redirect("articles:article_detail", article.pk)
- save(commit=False)
- 실제 데이터 베이스에 처리되지 않은 상태의 인스턴스를 반환합니다.
- 저장 전, 로직이 필요한 경우에 사용합니다.
comment = Comment()
comment.content = content
#### 이 지점을 잡아주는 것을 save메소드가 지원을 한다.! ####
comment.save() // 이 때 데이터베이스에 저장을 한다!
→ comment = form.save(commit=False)
→ 이렇게 하면 방금 새로 생성된 comment 인스턴스인데, commit은 되지 않아서 DB에는 아직 들어가지 않은 상태!
articles/templates/articles/article_detail.html
<hr>
<h3>댓글</h3>
<form action="{% url "articles:comment_create" article.pk %}" method="POST">
{% csrf_token %}
{{ comment_form.as_p }}
<input type="submit" value="댓글작성">
</form>
코멘트를 보여주는건 article detail 페이지를 눌렀을때 보여주기때문에 get은 필요없다!
댓글 읽기
articles/views.py
articles/templates/articles/article_detail.html
...
<ul>
{% for comment in comments %}
<li>
<p>{{ comment.content }}</p>
</li>
{% endfor %}
</ul>
템플릿에서 우리가 이미 article을 알고있기 때문에
댓글 목록 보여줄때
뷰에서 넘겨서
{% for comment in comments %}
이렇게 할 필요 없이 그냥
그런데 사실 이렇게도 가능해요!
⇒ view를 수정하지 않고 바로 해결 👀
<ul>
{% for comment in articles.comments.all %}
<li>
<p>{{ comment.content }}</p>
</li>
{% endfor %}
</ul>
도 가능하다!!
하지만 우리는 order by(-pk) 등을 사용해주기 위해 그냥 comments를 사용해본것.
과제 📝
아래 예시 사진처럼 결과가 나올 수 있도록 구현해볼까요?
- 댓글 삭제를 구현해 보세요.
- 전체 댓글의 수를 출력하도록 작성해 보세요.
'스파르타 내일 배움 캠프 AI 웹개발 과정 > Django framework' 카테고리의 다른 글
Model Relationship (M:N) / 좋아요, 팔로우 기능 구현 (1) | 2024.09.16 |
---|---|
Custom UserModel 활용하기 (1) | 2024.09.16 |
Django Admin (1) | 2024.09.12 |
Django Static & Media (0) | 2024.09.12 |
Django로 회원가입 기능 구현하기 (0) | 2024.09.11 |