[Django] clone instagram #5

์ •๋ณด๊ตฌ๋‹ˆยท2021๋…„ 12์›” 2์ผ
0

Django

๋ชฉ๋ก ๋ณด๊ธฐ
13/15
post-thumbnail

๋ธŒ๋ผ์šฐ์ €์—์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ฏธ์ง€, ๊ธ€, ์‚ฌ์šฉ์ž 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");
    : ์—…๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋ฉ”์ธํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ๋œ๋‹ค.



๐Ÿ”Ž ์ฐธ๊ณ 

๊ฐ•์˜
๊ฐ•์˜์ž๋ฃŒ
๋™๊ธฐ, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฐฉ์‹

0๊ฐœ์˜ ๋Œ“๊ธ€