python/Django

[Django] 클라이언트에서 파일을 다운로드 해보자.

끼발자 2022. 5. 25. 14:36
반응형

최근 의도치않게 웹을 설계하고있다.

장고를 처음 쓸 때 느꼈듯, 내가 html과 js를 쓰는건지 파이썬을 쓰는건지 헷갈릴 때가 많다.

각설하고,

이번 포스팅은 views에 다운로드하는 기능구현, html에서 form안에 있는 데이터를 전송하여 DB에서 다운로드.

 

1. html에서 form 데이터를 django에 전달.

아래는 지금 사용하고있는 html을 간단하게 적어놓은 코드이다.

table로 체크박스로 만들고, 체크가 되어있으면 해당 value를 서버로 전달하는 역할을 한다.

<form action="{% url 'yourname:download' %}" method='post' id="checkForm" name="checkForm">
    {% csrf_token %}
    <table>
		<tr><th><input type="checkbox" name="box">Temp</th></tr>
    </table>
</form>

내 경우엔, form태그 바깥에 버튼을 위치시켰다. 버튼 모양을 class='btn btn-info btn-xs'라는 css를 입혔지만, 

담백하게 기능만 쓰기위해 아래의 예시에선 제외했다.

<a href='#' onclick="javascript:document.checkForm.submit();">
	<button>Send</button>
</a>

버튼을 누르면, checkForm을 submit하게된다. 화면에 보이는 html은 사용자의 입맛에따라 바꾸자.

 

2. 전달받은 form데이터로 DB에서 조회 및 다운로드

이제  views를 수정해보자.

from django.http import StreamingHttpResponse
from wsgiref.util import FileWrapper

def download(request):
    temp_file = BytesIO()
    with zipfile.ZipFile(temp_file,'w',zipfile.ZIP_DEFLATED) as temp_file_opened:
        for name in dict(request.POST)['box']: #이 부분
            df_buf = pd.DataFrame().to_csv(index=False) #이 부분
            temp_file_opened.writestr(f'{name}.csv',df_buf.encode())
    temp_file.seek(0)
    response = StreamingHttpResponse(
        FileWrapper(temp_file),
        content_type='application/zip'
    )
    response['Content-Disposition'] = 'attachment;filename=Data.zip'
    return response

여기서 수정해야할 부분은 주석으로 정리해뒀다.

아마 위의 html을 그대로 썼다면, checkbox의 name이 box일테고, 그렇다면 request.POST['box']를 불렀을 때, 

checkbox의 value가 name에 나올 것이다. 

내 경우엔 사전으로 변환하지 않으면 마지막 객체만 뽑혀 나와서 dict()로 데이터타입을 바꿔주었다.

그 다음인데, 나는 mongoDB에서 checkbox에 해당하는 collection을 다운받아야했다. 입력받은 value로 DB에서 찾는 과정은

직접 수정해야하고, 버퍼에 쓰기위해서 to_csv를 사용한다. ( file_path를 주지 않으면 자동으로 string으로 기록되더라. )

다음으론 zipFile로 압축파일을 버퍼로 열고 box들을 반복하면서 버퍼에 기록한다.

마지막으로 StreamingHttpResponse를 이용해서 압축파일을 보낸 다음, return 하면 끝.

attachment;filename="" 이 안에는 여러분이 원하는 파일명을 사용하면 된다.

반응형