멋쟁이 사자처럼 10기/세션

2022/05/13 <1:N & M:N 세션>

cha2y0ung 2022. 6. 7. 19:08
728x90

Django model의 관계

1 : 1 부부 관계

1 : N 가족 관계

M : N 학교-학생 관계

 

1:N은 댓글, 좋아요  M:N은 해시태그로 구현된다

 

댓글 기능 구현

순서

1) models.py : Blog 와 1:N 관계인 모델 작성

2) bash : 변경한 모델을  migrate

3) admin.py : 관리자에 모델 추가 -> runserver로 모델이 추가 되었는지 확인

4) detail.html : 데이터베이스의 댓글을 보여주기 위한 코드 작성

5) admin page : 어드민 페이지에 접속하여 댓글 작성

6) bash :: runserver~!~!

 

1. 모델 작성(models.py)

속성명 타입 제한조건
post ForeignKey related_name, on_delete
username CharField max_length
comment_text TextField .
created_at DateTimeField default

ForeignKey : 데이터베이스에서 다른 테이블을 참조하기위해 사용

related_name : Blog 모델에서 댓글에 접근할 수 있게 함

on_delete : ForeignKey가 참조하는 데이터가 삭제되었을때 해당 요소를 처리하는 방법 명시

default :  기본 시간설정

 

from django.db import models
from django.utils import timezone

class Comment(models.Model):
	post = models.ForeignKey(Blog, related_name = 'comments', on_delete= models.CASCADE)
    #ForeignKey 가 참조하는 데이터 삭제되면 ForeignKeyField를 포함하는 모델 인스턴스(row)도 함께 삭제
    username = models.CharField(max_length = 20)
    comment_text = models.TextField()
    created_at = models.DateTimeField(default = timezone.now)

 

2. 모델을 데이터베이스에 반영

python manage.py makemigrations

python manage.py migrate

 

3. 관리자에 model 추가(admin.py)

from .models import Blog, Comment

admin.site.register(Blog)
admin.site.register(Comment)
#모델 추가할때마다 일일이 이름 추가 안하고 *입력하면 모두 선택하겠다는 의미

from .models import *
#이렇게!!

 

4. html 코드 작성(detail.html)

<br>
{% for comment in blog.comments.all %}
#blog에서 comment로 등록된 데이터를 가져와서 하나씩 보여줌
	<div clas = "comment">
    	<strong class = "username">{{ comment.username }}</strong>
# comment에서 username이라는 이름을 가진 속성의 데이터값 보여달라
        <div class = "date"> {{ comment.created_at }}</div>
        <p> {{ comment.comment_text|linebreaks }}</p>
        #강제 줄바꾼
    </div>
{% empty %}
# 등록된 데이터가 없을 경우 보여줄 내용 작성
	<p>아직 댓글이 없어요</p>
{% endfor %}

 

admin 페이지 말고 직접 댓글 달 수 있게-!!

 

django form이란?

사용자로부터 응답을 받을 코드를 모두 구현하지 않아도 되도록 미리 만들어져있는 form class

 

1) forms.py : Blog와 1:N 관계인 모델 작성

2) views.py : form과 html 파일을 연결해주는 함수 작성

3) urls.py : view를 이용해 댓글을 작성하는 페이지의 url 등록

4) detail.html : detail 페이지와 form을 연결해주는 '댓글 달기' botton 작성

5) add_comment.html : form을 보여줄 html 코드 작성

6) bash : runserver

 

1. 모델 작성(forms.py)

from dataclasses import field
from django import forms
from .models import Blog, Comment

class BlogForm(forms.ModelForm):
	class Meta:
    	model = Blog
        fields = [ 'title', 'body' ]

class CommentForm(forms.ModelForm):
	class Meta:
    	model = Comment
        fields = ['username', 'comment_text']

 

2. 함수 작성 (views.py)

from .forms import BlogForm, CommentForm
def add_comment(request, blog_id)L
	blog = get_object_or_404(Blog, pk = blog_id)
    
    if request.method == 'POST':
    form = CommentForm(request.POST)
    
    	if form.is_valid():
        	comment = form.save(commit = False)
            comment.post = blog
            comment.save()
            return redirect('detail', blog_id)
    else:
    	form = CommentForm()
    return render(request, 'add_comment.html', {'form' : form})

 

3.  url 등록 (urls.py)

path('<int:blog_id>/comment', blog.views.add_comment, name = "add_comment"),

 

4. html 코드 작성 (detail.html)

<hr>
<a class = "add_comment" href = "{% url 'add_comment' blog.id %}"> 댓글 달기</a>
{% for comment in blog.comments.all %}
	<div class = "comment">
    	<strong class = "username">{{ comment.username }}</strong>
        <div class = "date"> {{ comment.created_at }}</div>
        <p>{{ comment.comment_text|linebreaks }}</p>
    </div>

 

5. add_comment.html

{%block content%}
	<h3>New Comment</h3>
    <form method = "POST" class = "post-form">
    	{% csrf_token %}
        {{ form.as_p }}
        <button type = "submit" class = "save btn btn-default">등록</button>
    </form>
{% endblock %}

 

해시태그 기능 구현

모델 수정

class HashTag(models.Model):
	hashtag = models.CharField(max_length=100)
    
    def __str__(self):
    	return self.hashtag

class Blog(models.Model):
	title = models.CharField(max_length = 200)
    date = models.DateTimeField('date published')
    body = models.TextField()
    hashtag = models.ManyToManyField(HashTag)

admin.py 에 등록 (admin에 등록한 후에는 항상 makemigrations, migrate)

 

detail 함수 수정

<h3>{{blog.title}}</h3>
{{blog.date}}
<br>
{{blog.body}}
<br>
<div>
	{% for hashtag in hashtags.all %}
    #{{hashtag}}
    {%endfor%}
</div>

 

데이터 저장할 통 만들기 -> models.py

admin.py에 만든 통 등록

migrate

통에 담긴 데이터 사용위해 view.py 함수 수정

view.py가 전달한 데이터 출력하려면 html 파일 수정

 

게시글 작성 페이지에서 해시태그도 입력받을 수 있도록 input 추가해서 new.html 수정

<body>
	<h1>Creating Blog</h1>
    
    <form action = "{% url 'create' %}" method = "post">
    	{%csrf_token%}
        {{ form.as_p }}
        해시태그 <input type="text" name ="hashtags" placeholder = "해시태그 , 로 구분">
        <button type = "submit">제출</button>
    </form>
</body>

 

views.py 수정

new_blog.save()
hashtags = request.POST['hashtags']
hashtag = hashtags.split(",")
for tag in hashtag:
	new_hashtag = HashTag()
    new_hashtag.hashtag= tag
    new_hashtag.save()
    new_blog.hashtag.add(new_hashtag)
return redirect('detail', new_blog.id)

입력받은 해시태그를 hashtags에 담고 , 기준으로 쪼개 hashtag에 담는다

hashtag에 있는 여러개의 데이터를 각각 tag라는 이름으로 가져오기

블로그 객체의 해시태그에 추가해줌

 

 

해시태그 중복 문제

def create(request):
	form = BlogForm(request.POST, request.FILES)
    if form.is_valid():
    	new_blog = form.save(commit=False)
        new_blog.date = timezone.now()
        new_blog.save()
        hashtags = request.POST['hashtags']
        hashtag = hashtags.split(", ")
        for tag in hashtag:
        	new_hashtag = HashTag.objects.get_or_create(hashtag = tag)
            new_blog.hashtag.add(new_hashtag[0])
        return redirect('detail', new_blog.id)
    return redirect('home')

view 수정