(3) Django 인스타그램 피드화면 만들어보기 [데이터베이스]
이번 글에서는 만든 데이터베이스에 column을 추가하고, 그 값들로 화면을 구성해 볼 것이다.
지난 글을 죽 따라가면 이런 인스타그램 화면을 볼 수 있을 것이다.
이제부터 중요한 작업이 시작된다.
데이터베이스를 가져와서 뿌려줄거다.
일단, ORM
개념을 알아야한다. (object relational mapping)
과거에는 db의 테이블을 따로 만들고 실제 코드에서 DB에 사용하는 필드를 일일이 선언하고 조회해서 사용했다.
이때, sql문이 사용된다.
ORM(object relational mapping)?
코드에서 필드를 설정을 하면 꼭 DB에도 이중적으로 만들어줘야할까에 대한 의문에서 시작되었다.
이후 DB와 code둘 다 작성해주어야 정상적으로 작동되었던 과거의 방식에서, 객체의 개념을 따와 code 한쪽에만 만들면 자동으로 migration이 되면서, DB에 반영될 수 있는 방식으로 발전했다.
이로써 ORM에서 우리는 CODE만 관리하면 된다는 크나큰 장점이 생겼다.
뿐만아니라, SQL query 를 쓰지 않아도 된다.
user의 object에 filter메서드를 통해 namedl "누구"인 애를 찾아라 -> 그러면 code to SQL로 원하는 데이터를 가져올 수 있다. 이를 장고에서는 쿼리셋이라고 한다.
그럼 우리의 하나의 피드를 구성할 때 필요한 field들을 생각해보자!
프로필 사진 | 글쓴이 | 피드 이미지 | 좋아요수 | 댓글 |
참고로 하나의 column에는 하나의 값만 들어가야한다.
댓글
과 같은 필드는 여기에 쓰기 어렵다.
좋아요 수도 따로 테이블을 만들어서 가져오는 방식이 더 효율적이라고 한다.
다음은 댓글 테이블이다.
피드의 고유아이디 | 댓글쓴이 | 댓글내용 |
피드하나를 구성할 때, 피드 테이블에서 하나 가져와서 그리고, 피드 아이디에 해당하는 댓글 테이블의 column를 가져와서 보여주면된다.
이 개념은 기본키
와 외래키
의 개념을 사용하는데, 이 프로젝트에서는 외래키
에 대한 내용은 사용하지 않고 기본키(primary key)
만을 사용해서 만들 것이다.
마지막으로 좋아요테이블이다.
피드 아이디 | 좋아요한 사람 | 좋아요 여부 |
이렇게 구성한다면, 좋아요 개수를 헤아릴 때 중복을 막기에 좋을 것이다. 다만 이런 구성은 사용자가 매우 많을 때, 계산시간이 오래 걸릴 것 같다.
피드하나를 구성하는데 테이블이 3개나 필요하다니 ㄷㄷㄷ
이제 model을 만들자.
from django.db import models
# Create your models here.
class Feed(models.Model): # 괄호 안의 내용은 상속의 개념이다. 모델에 있는 내용을 가져다 쓰겠다는 말
# 필드 생성
content = models.TextField() # 글 내용
image = models.TextField() # 피드 이미지
profile_image = models.TextField() # 프로필 이미지
use_id = models.TextField() # 글쓴이
line_count = models.TextField() # 좋아요 수 (여기 오타있음 ㅜㅜ)
IntegerField
는 숫자를 표시하는 것 varchar
는 DB에서 사용된다. (DB를 더 배우면 알 수 있다.)
Feed에 대한 모델을 만들었다.
python manage.py makemigrations
의 명령어를 통해 migration을 하면, 자동으로 database로 만들어진다.
(venv) PS C:\Users\leath\PycharmProjects\instagramProject> python manage.py makemigrations
Migrations for 'Content':
Content\migrations\0001_initial.py
- Create model Feed
(venv) PS C:\Users\leath\PycharmProjects\instagramProject>
이렇게 뜨면 성공이다.
Content\migrations\0001_initial.py
이름의 migration파일이 생성된 것을 본인의 프로젝트에서 확인하자.
이제 이 migration 파일을 실행시켜 database에 추가하자.
열심히 추가했는데 그래서 어느 database에 생기는 것일까?
다시 settings.py
파일을 살펴보자
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
default로 sqlite3를 사용하는 것을 알 수 있다.
위에 코드에 작성되있는 것 처럼 우리의 프로젝트에도 db.sqlite3
이 이미 있는 것을 확인할 수 있다.
python manage.py migrate
이 명령어를 쳐서 database table을 생성해보자.
Operations to perform:
Apply all migrations: Content, admin, auth, contenttypes, sessions
Running migrations:
Applying Content.0001_initial... OK
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
이렇게 여러가지가 성공적으로 migrate된 것을 볼 수 있다.
우리는 맨 마지막에 해당하는 것만 만들려고 했는데, 이상한 것까지 만들어진 것을 확인할 수 있다.
이것이 무엇일까?
이는 django에서 기본적으로 제공하는 default 모델이다.(어드민과 같은..)
그럼 데이터베이스가 잘 생성되었는 지 확인하기 위해서 쿼리문을 다음과같이 작성해보자.
이렇게 확인할 수 있다. 참고로 장고는 database를 생성할 때 사용자가 따로 작업을 해주지 않는다면 id는 자동 생성된다.
(하.. 여기에서 실수로 필드명과 형을 잘못 입력해서 수정해주어야한다.)
(추가로,, community버전에서는 저 database sql을 직접적으로 확인할 수 있는 기능이 없어서 다른 방법을 사용해주어야한다고 한다..(그 방법은 모른..다...))
이제 데이터베이스를 직접 다루는 본격적인 코딩을 해보자.
우선은 urls.py 에서 화면 경로를 바꿔주자
from django.contrib import admin
from django.urls import path
from .views import Sub
from Content.views import Main
# url list를 두면된다.
# admin/ 은 default로 제공주는 것이다.
urlpatterns = [
path('admin/', admin.site.urls),
# path('', Sub.as_view()),
path('main/', Main.as_view()),
]
이렇게 Content안에 있는 views.py파일이 보이도록 수정했다.
views.py는
from django.shortcuts import render
from rest_framework.views import APIView
from .models import Feed ## .이 의미하는 바는 나랑 같은 폴더에 위치하고 있다는 말
# Create your views here.
class Main(APIView):
def get(self, request):
print("겟으로 호출")
feed_list = Feed.objects.all() # query set. == select * from content_feed;
print(feed_list)
for feed in feed_list:
print(feed.content)
render() # for문이 여기서 끝남을 명시적으로 알려주는 기능
return render(request, "instagram/main.html", context=dict(feeds=feed_list))
이렇게 바꿔준다.
1. feed_list
에는 피드에 대한 모든 데이터가 담긴다.
2. for문을 통해 데이터를 하나씩 살펴볼 수 있다.
3. 마지막 return문에서 context를 주목해야하는데, 딕셔너리(map)형식으로 key, value값을 통해 데이터를 화면단으로 넘겨줄 수 있다.
화면에서 볼 수 있도록 main.html을 아래와 같은 코드를 파일에 추가해보자.
<div>
{{ feeds }}
</div>
나는 nav바 위에 추가해봤다.
이렇게 위에 <QuerySet[]>
이 잘 들어왔음을 확인할 수 있다.
요소를 하나씩 보기 위해서는 for문을 활용해야 한다.
<div>
{% for feed in feeds %}
<p> {{ feed.content }}</p>
<p> {{ feed.user_id }}</p>
<p> {{ feed.line_count }}</p>
{% endfor %}
</div>
{% endfor %}
은 for문이 끝났다는 표시를 해주는 것이다.
이를 활용해서 feed를 반복문으로 만들어보자
이렇게 column에 있는 항목들이 화면단에 잘 나온것을 확인할 수 있다.