위스타그램 4 업로드 (로그인 데코레이터)
29 Jul 2021 | 입문 위코드 TIL[Mission 7] 게시물 등록 기능 구현
1. Postings app 생성
- Django에서는 주로 다루는 데이터의 종류가 달라지는 시점에서 앱을 분리합니다. 인스타그램의 게시물은 이용자 데이터와는 그 성질이 달라 데이터베이스에서 테이블을 따로 관리합니다. 따라서, 주로 다루는 테이블이 달라지므로 앱을 분리하는 것이 좋습니다.
2. Posting Model 생성
- 인스타그램에 게시물을 등록하기 위해서는 사용자, 생성 시간, 이미지 url이 필요합니다.
- 해당 게시물의 유저는 Foreign Key를 이용하여 이미 서비스에 가입된 사람으로 연결시켜 주세요.
from django.db import models
from users.models import User
class Upload(models.Model): #나는 포스팅대신 업로드라는 이름을 사용했다
user_id = models.ForeignKey(User, on_delete=models.CASCADE, db_column='user_id')
#User테이블의 id를 참조하는 'user_id'이름의 컬럼을 만든다.
created_at = models.DateTimeField(auto_now_add=True)
text = models.CharField(max_length=300)
img = models.CharField(max_length=400)
class Meta:
db_table = 'uploads'
데이터베이스 상의 필드 이름(db_column)은 테이블에 정의될 이름을 의미한다. db_column 매개변수를 사용하지 않는다면, 데이터베이스 필드에 작성될 필드명은 user_id_id가 되는데 이는 의도한 필드명이 아니므로, db_column 매개변수의 인수에 user_id를 사용한다.
3. Postings View 작성
:: 게시물 등록
- 게시물 등록 클래스를 생성해주세요.
- 게시물을 등록할 때에는
post
메소드를 사용합니다. - 게시물 생성 시간은 등록하는 현재 시간이어야 합니다.
:: 게시물 표출
- 등록된 모든 게시물을 나열하는 게시물 표출 클래스를 생성해주세요.
- 게시물을 나타낼 때에는
get
메소드를 사용합니다. - 게시물을 나타낼 때에는 등록한 사람, 게시물, 게시된 내용, 게시된 시각이 포함되어야 합니다.
import json
from django.views import View
from django.http import JsonResponse
from .models import Upload as UploadModel
#AttributeError: type object 'Upload' has no attribute 'objects'
#이 에러가 자꾸나서 스택오버플로우에서 찾은대로 as UploadModel로 갈음해주었다.
from users.models import User
from users.utils import login_decorator
#데코레이터는 유저스앱안에 따로 유틸스파일에 들어있다.
class Upload(View):
@login_decorator #유저가 올바른 토큰을 가져왔다면
def post(self, request):
try:
data = json.loads(request.body)
if (data["img"] == ""): #이미지가 없으면 에러
return JsonResponse({"message": "EMPTY_IMAGE"}, status=400)
UploadModel.objects.create( #디비에 값을 추가
user_id = User.objects.get(id = request.user.id),
#요청을 수행하는 유저의 아이디
img = data["img"],
text = data["text"]
)
return JsonResponse({"message": "SUCCESS"}, status=201)
except KeyError:
return JsonResponse({"message": "KEY_ERROR"}, status=400)
def get(self, request):
uploads = UploadModel.objects.all()
#업로드모델에 따라 객체를 다 가져와서 저장
results = []
for upload in uploads: #저장된 객체들을 한 개씩 돌면서
results.append({
"user_id" : upload.user_id.id,
#객체의 유저아이디번호에 해당하는 id
"img" : upload.img,
"text" : upload.text,
"created_at" : upload.created_at
})
return JsonResponse({"results": results}, status=200)
Decorater의 구조
import jwt
from django.http import JsonResponse
from django.core.exceptions import ObjectDoesNotExist
from my_settings import SECRET_KEY
from .models import User
def login_decorator(func):
def wrapper(self, request, *args, **kwargs):
#들어올 수 있는 인자를 모두 받도록 한다
try:
token = request.headers.get("Authorization", None)
#헤더에서 Authorization(헤더에 있는 속성)을 가져와서 토큰에 저장한다.
user = jwt.decode(token, SECRET_KEY, algorithms='HS256')
#토큰을 시크릿키를 이용해 디코드해서 유저 아이디를 알아내서 유저에 저장한다.
request.user = User.objects.get(id = user['id'])
#유저의 아이디에 해당하는 유저객체를 리퀘스트.유저에 저장한다.
return func(self, request, *args, **kwargs)
#받은 인자들을 모두 전달해준다(예를 들어 이미지, 텍스트 등등)
except jwt.exceptions.DecodeError:
return JsonResponse({"message" : "INVALID_TOKEN"}, status=400)
except ObjectDoesNotExist:
return JsonResponse({"message" : "INVALID_USER"}, status=400)
return wrapper
4. Urls.py 작성
클라이언트의 요청을 받아서 게시판 뷰를 호출할 수 있도록 urls.py 를 작성해야합니다.
- ✅ 적절한
url
작성
#상위프로젝트폴더urls.py
from django.urls import path,include
urlpatterns = [
path("users",include("users.urls")),
path("upload",include("upload.urls"))
]
#하위앱폴더urls.py
from django.urls import path
from .views import Upload
urlpatterns = [
path("", Upload.as_view())
]
POSTMAN을 이용해서 Headers에 Authorization값을 넣고 Body에 JSON형식으로 값을 넣어서 디비에 이미지링크과 텍스트가 잘 입력된 모습을 볼 수 있다.