๋ธ๋ผ์ฐ์ ์์ ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ฏธ์ง, ๊ธ, ์ฌ์ฉ์ id, ์ฌ์ฉ์ ํ๋กํ์ฌ์ง์ ์ฌ๋ฆฌ๋ฉด ์ฅ๊ณ ์๋ฒ์ธ vies.py
์์ ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ชจ์ ๋๋น์ ์ ์ฅํ ๊ฒ์ด๋ค.
์ด๋ ์ด๋ฏธ์ง, ๊ธ, ์ฌ์ฉ์id, ์ฌ์ฉ์ ํ๋กํ์ฌ์ง๊ณผ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ์ ๋ก๋ ํ๋ ๊ฒ์ด ์กฐ๊ธ ์ด๋ ค์ธ ์ ์๋ค.
์ฐ์ ํผ๋ ์์ฑ์ ์ํด ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ค ๊ฒ์ด๋ค.
์ฌ๊ธฐ์ ๋๊ธฐ, ๋น๋๊ธฐ๋ ๋ฌด์์ผ๊น?
๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์๋ ๋๊ธฐ(synchronous)
, ๋น๋๊ธฐ(asynchronous)
์ฒ๋ฆฌ๊ฐ ์๋ค.
ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒํํ ์ด๋ค ์์ฒญ์ ํ๋ฉด ์๋ฒ๋ ์๋ต์ ์ฃผ๊ฒ๋๋ค.
์ด๋ ๋๊ธฐ ๋ฐฉ์์ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ณด๋์ ๋ ์๋ต์ ์ค๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋ฐฉ์์ด๋ฉฐ, ์๋ต์ด ๋์์์ผ ๋ค์ ๋์์ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ A์์ ์ด ๋ชจ๋ ์งํ ๋ ๋๊น์ง B์์ ์ ๋๊ธฐํด์ผํ๋ค.
๋ฐ๋ฉด์ ๋น๋๊ธฐ ๋ฐฉ์์ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ณด๋์๋ ์๋ต์ ๊ธฐ๋ค๋ฆฌ์ง ์๋ ๋ฐฉ์์ด๋ค. ์๋ต ์ํ์ ์๊ด์์ด ๋ค์๋์์ ์ํํ ์ ์์ผ๋ฉฐ, A์์
์ด ์์ํ๋ฉด ๋์์ B์์
์ด ์คํ๋๋ค.
A์์
์ ๊ฒฐ๊ณผ๊ฐ์ด ๋์ค๋๋๋ก ์ถ๋ ฅ๋๋ค.
์ด ๊ทธ๋ฆผ์ ๋ณด๋๊น ๋จ๋ฒ์ ์ดํด๊ฐ ๋์๋ค..ใ
API
๋ง๋ค๊ธฐ๊ณต์ ํ๊ธฐ
๋ฒํผ์ ๋๋ฅด๋ฉด ์์์ ๋งํ๋ ์ด๋ฏธ์ง, ๊ธ, ์ฌ์ฉ์id, ์ฌ์ฉ์ ํ๋กํ์ฌ์ง์ ์๋ฒ๋ก ๋ณด๋ด ์ค ์ค์ ๋ก ํผ๋๊ฐ ์์ฑ๋ ์ ์๋๋ก ํด์ผํ๋ค.
์ฐ์ , ๊ณต์ ํ๊ธฐ
๋ฒํผ์ ๋๋ ์ ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ์ฝ๋๋ฅผ ์์ฑํด์ฃผ๋๋ก ํ๊ฒ ๋ค.
html
...
<textarea id = "modal-input-txt" class="modal-text-textarea form-control col-sm-5" rows="10" placeholder="๋ฌธ๊ตฌ ์
๋ ฅ..."></textarea>
...
<button id = "modal-create-btn" type="button" class="btn btn-primary" style="width: 268px">๊ณต์ ํ๊ธฐ</button>
...
jquery
let files; // ์ ์ญ๋ณ์ ์ค์
...
...
function uploadFiles(e){
...
files = e.dataTransfer.files;
$('#modal-create-btn').click(function(){
alert("๊ณต์ ํ๊ธฐ ํด๋ฆญ!");
let file = files[0];
let image = files[0].name;
let content = $('#modal-input-txt').val();
let user_id = "jollyn";
let profile = "https://pbs.twimg.com/profile_images/1324185005883486208/gOBh4kKR_400x400.jpg";
});
id
๊ฐ์ ์ค์ ํด ์ค๋ค, ์ ์ด์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒํผ์ ํด๋ฆญํ์ ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋๋ก ๋ง๋ค์ด ์ฃผ์๋ค.
์ด๋ image
๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด์
์๋จ์ files
๋ฅผ ์ ์ญ๋ณ์๋ก ์ ์ธํด์ฃผ๊ณ files
๋ฅผ ์ฌ์ฉํด์ค๋ค.
์ฌ๊ธฐ์ files
๋ฅผ ์ ์ญ๋ณ์๋ก ์ ์ค์ ํด์ฃผ๋๊ฐ?
๊ธฐ์กด์ files๋ function uploadFiles(e)
ํจ์ ์์์ ์ ์ธ๋์ด ์๋ ์ํ์๋ค. ์ด files๋ผ๋ ๋ณ์๋ฅผ ๋ค๋ฅธ ๊ณณ์์๋ ์ฌ์ฉํ๊ธฐ ์ํด ์๋จ์ ์ ์ญ๋ณ์๋ก ์ค์ ํด์ค์ผ ํ๋ค.
์ด์ ๋ด์ ๋ฐ์ดํฐ๋ฅผ ajax
๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ๋ฅผ ๋ณด๋ด์ฃผ๋๋ก ํ๊ฒ ๋ค.
๋จผ์ ํ์ผํ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ฃผ๊ธฐ ์ํด์๋ formdata
๋ฅผ ํ๋ ๋ง๋ค์ด์ค์ผ ํ๋ค.
jquery
let fd = new FormData();
fd.append('file', file);
fd.append('image', image);
fd.append('content', content);
fd.append('user_id', user_id);
fd.append('profile', profile);
๋ง๋ค์ด ์ค ๋ค, ajax
ํธ์ถ์ ๋ง๋ค์ด ์ฃผ๋๋ก ํ๊ฒ ๋ค.
$.ajax({
url: "/content/upload",
data: fd,
method: "POST",
processData: false,
contentType: false,
success: function (data) {
console.log("์ฑ๊ณต");
},
error: function (request, status, error) {
console.log("์๋ฌ");
},
complete: function() {
console.log("์๋ฃ");
}
})
์ฝ๋๋ฅผ ํด์ํด๋ณด์๋ฉด,
์ด ajax๋ฅผ ํตํด์ /content/upload
url๋ก fd
๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ post
ํธ์ถ์ ํ๋ฉฐ,
์ฑ๊ณตํ๋ฉด console.log("์ฑ๊ณต")
๋ฅผ
์คํจํ๋ฉด console.log("์๋ฌ")
๋ฅผ
์ฑ๊ณต์ด๋ ์คํจ๋ console.log("์๋ฃ")
๋ฅผ ๋ฌด์กฐ๊ฑด ์คํํ๋ผ๋ ์๋ฏธ์ด๋ค.
ํ์ง๋ง ์ด ์ํ์์๋ /content/upload
์ด๋ผ๋ url์ ๋ง๋ค์ด์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋๋ค.
๊ทธ๋ผ ์ด์ ์๋ฒ์ชฝ์์ ์ฝ๋๋ฅผ ์์ฑํด์ค ์ฐจ๋ก์ด๋ค.
content/view.py
class UploadFeed(APIView):
def post(self, request):
file = request.data.get('file')
image = request.data.get('image')
content = request.data.get('content')
user_id = request.data.get('user_id')
profile = request.data.get('profile')
return Response(status=200)
instagram/urls.py
from content.views import Main, UploadFeed
urlpatterns = [
path('admin/', admin.site.urls),
path('main/', Main.as_view()),
path('content/upload', UploadFeed.as_view())
]
์๋ฒ๋ ajax
๋ก๋ถํฐ fd
๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ์๋ก์ด ํผ๋๋ฅผ ๋ง๋ค์ด์ค์ผํ๋ค.
views.py
์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ๋ด์์ฃผ๊ณ ํด๋ผ์ด์ธํธ์๊ฒ status=200
์ธ ์๋ต์ ์ฃผ๋ ํจ์๋ฅผ ๋ง๋ค์ด์ค๋ค.
๋ํ views.py
์ ํจ์๋ฅผ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ urls.py
์์ ํด๋น ํจ์์ ๋ํด url
์ ํ ๋น์์ผ์ค๋ค.
url์ ํ ๋น์์ผ ์ฃผ๋ฉด content/upload
๋ก ์ ์ํ ๊ฒฝ์ฐ content.views
์ UploadFeed
๋ฅผ ์คํ์ํฌ ๊ฒ์ด๋ค.
DB
์ ๋ฐ์ดํฐ ์ ์ฅํ๊ธฐ์ด์ ๋ด์์ค ๋ฐ์ดํฐ๋ฅผ ๋๋น์ ์ ์ฅ์์ผ์ค์ผ ํ๋ค.
์ด๋ ๊ธฐ์ตํด์ผ ํ ๊ฒ์,
๋๋น์๋ ํ์ผ์ด ์ค์ ๋ก ์ ์ฅ๋์ง ์๋๋ค๋ ๊ฒ์ด๋ค
์ค์ ํ์ผ์ ํ์ผ,์ด๋ฏธ์ง ์๋ฒ์ ์ ์ฅ๋๊ณ , ๊ทธ ์ฃผ์๋ง ๋๋น์ ์ ์ฅํด์ค ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ค์ ํ์ผ์ ์ด๋์ ์ ์ฅํ ๊น?
์ฅ๊ณ ์์๋ midea
๋ผ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์ฅ๊ณ ํ๋ก์ ํธ ์๋ฒ์ ํ์ผ์ ์ ์ฅ์ํฌ ์ ์๋ค.
์ด midea
๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ setting.py
์ ๋ค์ ์ฝ๋๋ฅผ ์์ฑํด์ค์ผ ํ๋ค.
instagram/settings.py
import os
...
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
์ ์ฝ๋๋ฅผ ์์ฑํด์ฃผ๋ฉด,
์ฅ๊ณ ์์ ์ฌ์ฉ์๊ฐ ์๋น์ค์์ ์ฌ๋ฆฌ๋ ๋ฏธ๋์ดํ์ผ๋ค์ด ๋ฏธ๋์ด ํด๋์ ์ ์ฅํด์ค๋ค.
์ถ๊ฐ๋ก ์ฌ์ฉ์๋ค์ด ์
๋ก๋ํ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก media
์ ๋ํ url๋ ์์ฑํด์ค์ผ ํ๋ค.
instagram/urls.py
from .settings import MEDIA_ROOT, MEDIA_URL
from django.conf.urls.static import static
urlpatterns += static(MEDIA_URL, document_root=MEDIA_ROOT)
์ด ์ฝ๋๋ฅผ ์ถ๊ฐํด์ค์ผ media
์ ์ด๋ฏธ์งํ์ผ์ด ์ ์ฅ๋๋ฉด ๋ฏธ๋์ด ํ์ผ์ ์ ๊ทผํด์ ์กฐํํ ์ ์๋ค.
์ถ๊ฐํด์ฃผ์ง ์์ผ๋ฉด ์ด๋ฏธ์ง ํ์ผ์ ๋ฃ์ด๋ ๋์ค์ ์กฐํํ ์ ์์ !!
๊ทธ๋ผ ์ด์ ์ด๋ฏธ์งํ์ผ์ด ์ ์ฅ ๋ media
๋ผ๋ ํด๋๋ฅผ ๋ง๋ค์ด์ฃผ๋๋ก ํ๊ฒ ๋ค.
instagram/
content/
instagram/
venv/
templates/
user/
media/ ๋ฏธ๋์ด ํด๋ ์์ฑ
manage.py
๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด content/views.py
๋ฅผ ์์ ํด์ฃผ๋๋ก ํ๊ฒ ๋ค.
content/views.py
import os
from instagram.settings import MEDIA_ROOT
from uuid import uuid4
class UploadFeed(APIView):
def post(self, request):
file = request.FILES['file']
uuid_name = uuid4().hex
save_path = os.path.join(MEDIA_ROOT, uuid_name)
with open(save_path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
image = request.data.get('image')
content = request.data.get('content')
user_id = request.data.get('user_id')
profile = request.data.get('profile')
Feed.objects.create(image=image, content=content, user_id=user_id, profile=profile)
return Response(status=200)
์ฝ๋๋ฅผ ํด์ํด๋ณด์๋ฉด, ๋ค์๊ณผ ๊ฐ๋ค
uuid_name = uuid4().hex
์ด๋ฏธ์ง ํ์ผ์ ์ด๋ฆ์๋ ํ๊ธ์ด๋ ํน์๋ฌธ์๋ค์ด ๋ค์ด๊ฐ ์ ์๋ค. ๊ทธ๋ด๊ฒฝ์ฐ ์๋ฒ์์ ์ด๋ฆ์ ์ฝ์๋ ์๋ฌ๊ฐ ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง ํ์ผ์ ์ ์ฅํ ๋๋ ๋๋ค์ผ๋ก ์์ด์ ์ซ์๋ก ์ด๋ฃจ์ด์ง ๊ณ ์ ํ id๊ฐ์ ๋ฃ์ด์ ์ ์ฅํ๋ค.
์ด๋ ๊ณ ์ ํ id๊ฐ์ ์ฃผ๊ธฐ ์ํด uuid4()
๋ผ๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
save_path = os.path.join(MEDIA_ROOT, uuid_name)
์ ์ฅ๊ฒฝ๋ก๋ฅผ MEDIA_ROOT
์ uuid_name
์ ์ฐ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
์ด๋ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
์ด๋ฏ๋ก
BASE_DIR
์ฆ ํ์ฌ ํ๋ก์ ํธ ๊ฒฝ๋ก์ media
๋ฅผ ๋ถ์ด๊ณ , uuid
์ด๋ฆ์ ๋ถ์ฌ์ ์ ์ฅํ๊ฒ ๋ค๋ ๊ฒ์ด๋ค.
์ค์ ๋ก ํ์ผ์ด ์ ์ฅ๋๋ ์์น๋ instagram/media/uuid4sjdkfsffdn
์ด๋ฐ ํํ๊ฐ ๋๋ค.
with open(save_path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
์ค์ ๋ก ํ์ผ์ midea
์ ์ ์ฅ์์ผ ์ฃผ๋ ๋ถ๋ถ์ด๋ค.
Feed.objects.create(image=image, content=content, user_id=user_id, profile=profile)
๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ํผ๋๋ฅผ ๋ง๋ค์ด์ค๋ค.
์๋ฒ๋ฅผ ์คํํด ์ค์ ๋ก ์ฌ์งํ์ผ์ ์ ๋ก๋ ์ํค๋ฉด ํผ๋๊ฐ ์์ฑ๋๋ ํ์ธํด ๋ณด๋๋ก ํ๊ฒ ๋ค
์์ฒ๋ผ ์ฌ์ง์ด ๋ค์ด์ค์ง ์๋๋ค๋ ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
์๋ํ๋ฉด ํ์ฌ ๋๋น์ ์ ์ฅ๋ ์ด๋ฏธ์ง ์ฃผ์๊ฐ http๋ก ์์ํ๋ ํ๋ค์์ด ์๋ ํ์ผ๋ค์๋ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ผ์ ๋ฏธ๋์ด ํ์ผ๋ค์์ ์๋์ผ๋ก ์ฝ์ ์ ์๋๋ก ํด์ค์ผํ๋ค.
main.html
์ ์ด๊ณ ๋๋น์ feed.image
๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ถ๋ถ์ ์์ ํด์ฃผ๋๋ก ํ๊ฒ ๋ค.
templates/instagram/main.html
{% load static %}
{% for feed in feeds %}
...
...
<div class="feed-img">
<img id="feed-img"
src="{% get_media_prefix %}{{ feed.image }} ">
</div>
{% get_media_prefix %}
๋ฅผ ๋ฃ์ด์ค์ผ๋ก์จ ํ์ผ๋ค์์ ์๋์ผ๋ก ์ฝ์ด์ฌ ์ ์๊ฒ ๋๋ค.
์ด๋ ๋ฐ๋์ {% load static %}
์ ํด์ค์ผ settings.py
์์ ์ค์ ํด์คฌ๋ MEDIA_ROOT
๋ฅผ ์ฝ์ด์ฌ ์ ์๋ค
์์ ํ ์๋ฒ๋ฅผ ์คํํด๋ณด๋ฉด ์๋์ ๊ฐ์ด ์ด๋ฏธ์งํ์ผ์ด ์ ๋ค์ด์ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค
์ ๋ก๋๊ฐ ์๋ฃ๋๋ฉด ๋ชจ๋ฌ์ด ๋ซํ๋๋ก ์ฝ๋๋ฅผ ์์ ํด์ฃผ๋๋ก ํ๊ฒ ๋ค.
templates/instagram/main.html
$.ajax({
url: "/content/upload",
data: fd,
method: "POST",
processData: false,
contentType: false,
success: function (data) {
console.log("์ฑ๊ณต");
},
error: function (request, status, error) {
console.log("์๋ฌ");
},
complete: function() {
console.log("์๋ฃ");
// ์
๋ก๋ ์๋ฃํ๋ฉด mainํ์ด์ง๋ก ์๋ก๊ณ ์นจ
location.replace("/main");
}
})
location.replace("/main");
๐ ์ฐธ๊ณ