[Django] clone instagram #3
이제부터 실제로 작동시키기 위해 백엔드 부분을 만져보도록 할 것이다.
ORM
디비의 오리지널 방식을 먼저 알아보자.
디비 만들고 코드 따로 만들고 조회하는 것 따로 만들어서 화면에 보여준다.
여기서 조회할때는 SQL
을 사용한다.
즉, 오리지널 방식은 코드에서 디비를 select하여 데이터를 가져와 데이터를 채우고 화면에 보여주는 방식이다.
오리지널 방식에서는 코드에서 변수(name
,age
,gender
,email
)에 대해 모두 선언을 해주고, 디비에서도 (이름
,나이
,성별
,이메일
)을 넣어줘야 한다.
이러한 오리지널 방식에서 디비에 전화번호
를 추가해줄 경우,
코드에서 추가해주지 않았을 때 데이터가 누락되는 일이 발생하게 된다.
전화번호
라는 데이터를 가져오기 위해서는 코드에서도 phone
이라고 이중작업을 해줘야하는 것이다.
이렇게 이중작업을 해야하는 문제때문에 ORM
이라는 방식이 생기기 시작한 것이다.
그럼 ORM
방식은 무엇이 다를까?
ORM
은 객체(object)를 기반으로 디비를 만들어준다.
코드에서 class user
라는 객체에 이름
,나이
,성별
,이메일
을 만들어 주면
ORM
이 db
와 object
를 자동으로 마이그레이션 해준다.
마이그레이션을 통해 디비에는 코드에 있는 object 그대로 user
라는 테이블에 저장된다.
따라서 데이터 추가나 수정사항이 있어도 코드와 디비가 자동으로 마이그레이션되기때문에
양쪽을 모두 관리할 필요없이 코드만 관리해주면 된다.
또한 ORM
은 sql
쿼리문을 작성하지 않아도 된다. 코드를 작성하면 ORM
이 알아서 코드를 sql
로 바꿔준다.
장고에서는 이것을 '쿼리셋'이라고 한다.
DB
구상하기
그럼 이제 피드에 대한 데이터베이스를 만들어줘야 한다.
ORM
은 object
를 기반으로 디비를 만들기 때문에 데이터베이스를 만들기 위한 object
가 무엇일지 생각해봐야 한다.
데이터베이스는 쉽게 엑셀형식이라고 생각하면 된다. 하나의 column(열)에 하나의 값만 들어갈 수 있다
다음 피드와 댓글의 내용을 보여주기 위한 데이터베이스를 구상해보자면 다음과 같다.
>> 피드 table <<
프로필사진 | 글쓴이아이디 | 사진 | 글내용
>> 댓글 table <<
댓글남긴사람 | 댓글내용
피드를 보여줄 때 댓글까지 보여주고 싶다면,
첫번째 피드에 대한 데이터를 가지고 첫번째 피드를 그려준 다음,
댓글 테이블에서 피드id
를 1
로 갖는 데이터들을 모두 가지고 화면에 그려주게 된다.
이렇게 하나의 피드를 그리는데 하나의 테이블만이 필요한 것이 아니라 여러개의 테이블이 필요할 수도 있다.
여러개의 테이블이 필요한 경우에는 고유한 id값을 이용해서 데이터를 서로 연결시킬 수 있다.
db에서는 이러한 고유id값으로
Primary key
(기본키)와 Foreign key
(외래키)라는 것을 사용한다.
서비스에 따라서 데이터베이스의 구조 즉, 테이블이 어떻게 구성되는지 바뀌기 때문에
원하는 서비스가 어떤건지, 어떠한 기능을 하는지를 잘 알아야 디비의 테이블을 어떻게 구성할 것인지 알 수 있다.
models
만들기
디비를 구상해보았으니 실제로 코드에 객체를 만들어주도록 하겠다.
- content/models.py
class Feed(models.Model): # Feed라는 객체의 데이터베이스 만들기
profile = models.TextField() # 프로필사진
user_id = models.TextField() # 사용자아이디
image = models.TextField() # 사진
content = models.TextField() # 글내용
like_count = models.IntegerField() # 좋아요수
코드를 살펴보면,
TextField()
와 같이 디비에 해당 필드가 어떤 데이터형식을 표시하는지 정의해줄 수 있다.
이렇게 Feed
라는 객체에 대해 다섯개의 필드를 만들어 준 뒤, 마이그레이션을 해준다.
(venv)
python manage.py makemigrations
마이그레이션을 해주면 장고에서 자동으로 사용자가 models
에 선언한 클래스(객체)를 모두 찾아서 디비로 만들어줄 작업을 하게된다.
(venv)
python manage.py migrate
그럼 디비에 content_feed
라는 테이블로 위에서 만들어준 5개의 필드가 만들어지고 추가로 id
라는 고유값이 자동으로 만들어진다.
views
만들기
models.py
로 DB
를 만들어 줬으면, 이제 데이터를 어떻게 템플릿으로 전달해줄지 views
를 만들줘야 한다.
-content/views.py
from .models import Feed
class Main(APIView):
def get(self, request):
feed_list = Feed.objects.all()
return render(request, "instagram/main.html", context=dict(feed_list=feed_list))
코드를 해석해보자면, 다음과 같다.
feed_list = Feed.objects.all()
:Feed
테이블에 있는 모든 데이터를 가져온다return render(request, "instagram/main.html", context=dict(feed_list=feed_list))
: 데이터베이스에서 가져온 데이터를 담아서instagram/main.html
에 보내준다.
이렇게 뷰에서는 디비에 있는 데이터를 가져와서 템플릿으로 보내주게 된다.
url
연결하기
main/
이라는 url을 받았을 때 방금전 뷰에서 만들어준 Main
을 호출하기 위해서 url.py
파일을 수정해준다.
- instagram/urls.py
from content.views import Main
urlpatterns = [
path('admin/', admin.site.urls),
path('main/', Main.as_view())
]
url을 설정해줌으로써 main/
이라는 url을 타고 들어올 경우 content
앱에 있는 views
의 Main
을 호출하게 된다.
템플릿에 데이터 넣어주기
뷰로부터 넘어온 데이터를 템플릿에 적용시켜주도록 하겠다.
받아온 데이터를 템플릿에 적용시켜 줄때는 다음과 같은 방식을 사용한다.
{% for feed in feed_list %}
<p>{{ feed.id }}</p>
<p>{{ feed.image }}</p>
<p>{{ feed.content }}</p>
<p>{{ feed.profile_image }}</p>
<p>{{ feed.user_id }}</p>
<p>{{ feed.like_count }}</p>
{% endfor %}
반복문이 시작하는 지점에 {% for feed in feed_list %}
을 넣어주고, 반복문이 끝나는 지점에 {% endfor %}
를 넣어준다.
그리고 받아온 데이터값을 넣어줄 곳에 {{ feed.필드이름 }}
을 넣어주면, 알아서 데이터베이스에 있는 값들이 들어오게 된다.
이것을 바탕으로 이전에 작성해준 main.html
파일을 수정해보도록 하겠다.
- templates/instagram/main.html
...
<!-- 피드박스 시작 -->
{% for feed in feeds %}
<div class="feed-box">
<div class="profile">
<div class="profile-img-box">
<img class="profile-img"
src=" {{ feed.profile }} ">
</div>
<div class="profile-id">
{{ feed.user_id }}
</div>
</div>
<div class="feed-img">
<img id="feed-img"
src=" {{ feed.image }} ">
</div>
<div class="icon">
<div>
<span class="material-icons-outlined">favorite_border</span>
<span class="material-icons-outlined">chat_bubble_outline</span>
<span class="material-icons-outlined">send</span>
</div>
<div>
<span class="material-icons-outlined">bookmark_border</span>
</div>
</div>
<div class="like">
django <b>외 {{ feed.like_count }}명</b>이 좋아합니다
</div>
<div class="feed-text">
<b>{{ feed.user_id }}</b> {{ feed.content }}
</div>
<div class="comment">
<div> <b>기덕</b> 장고 화이팅 </div>
<div> <b>재명</b> 알고리즘 화이팅 </div>
<div> <b>이성</b> 파이썬 화이팅 </div>
</div>
<div class="input-comment">
<input id="input-comment" type="text" class="form-control" placeholder="댓글 달기...">
</div>
</div>
{% endfor %}
이때 한가지 수정해줘야할 부분이 있다.
지금은 가장 최근에 추가된 데이터가 피드 아래에 생기고 있다.
원래는 최근에 추가된 데이터가 가장 최신글로 상단에 떠야하기 때문에 이를 수정해줘야한다.
가장 최근에 추가된 데이터의 id
값이 가장 클 것이다.
원래는 뷰에서 디비를 가져올때 id
값이 작은거 부터
즉, 1 >> 2 >> 3번 순서대로 가져온다.
따라서 이 순서를 역순으로 가져오게 수정해보도록 하겠다.
- content/veiws.py
class Main(APIView):
def get(self, request):
feed_list = Feed.objects.all().order_by('-id')
return render(request, "instagram/main.html", context=dict(feeds=feed_list))
.order_by('-id')
:id
값이 큰것부터 가져옴
이렇게 수정한 뒤 서버를 돌리면 최신글이 최상단에 올라오도록 수정된 것을 확인 할 수 있다.
Author And Source
이 문제에 관하여([Django] clone instagram #3), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jollyn/Django-clone-instagram-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)