1. 목표
Django admin 페이지로 어떤 파일들을 모아서 압축 파일을 생성하는 비동기 작업이 완료되면, 그것들을 다운로드 받을 수 있는 페이지 제작
2. 구조
3. 구조 설명
3-1. django admin
django admin은 모델을 생성하고 admin에 등록하면, admin 주소로 들어오는 요청을 보낼 수 있는 FORM과 화면을 구성하는 TEMPLATE을 간단히 만들 수 있도록 해준다.
@admin.register로 admin에 모델을 등록하고 get_urls로 path와 일치하는 요청이 들어왔을 때 특정 view로 가서 로직을 처리하게 할 수 있다.
meta_data로 app_label값과 model_name값을 불러와서 view의 name을 동적으로 만들어줄 수 있다. 이 name값은 해당 view가 다른 곳에서 불리는 이름이다. 예를 들어 reverse("admin:function_simple-model_compressed_image_download")로 해당 view의 호출이 가능하다. (만약 meta_data의 정보가 각각 function, simple-model인 경우)
@admin.register(SimpleModel, site==admin_site)
class SimpleModelAdmin(admin.ModelAdmin):
simple_model_download_template="admin/simple_model_donwload.html"
## 중략
def get_urls(self):
urls = super().get_urls()
meta_data = self.model._meta.app_label, self.model._meta.model_name
return [
path(
"<path:model_id>/compressed-image-download/",
view=self.compressed_image_download_view,
name="%s_%s_compressed_image_download" % meta_data,
),
# ...
3-2. view -> template
이 view에서는 context 정보를 만들어서 template에 넘긴다.
render() 함수는 request, template, context 정보를 인자로해서 template으로 넘길 수 있다. template은 위 SimpleModelAdmin class 자체에서 정의한 html template 주소이다.
def snapshot_aerial_images_download_view(self, request, model_id):
obj = get_object_or_404(self.get_queryset(request), id=model_id)
context = self.admin_site.each_context(request)
context.update(
{
"object": obj,
"title": "SimpleModel Images Download",
}
)
return render(request, self.simple_model_download_template, context)
template은 상대 위치로 기술되어 있는데, template과 관련한 정보는 settings에 다음과 같이 정의해주면 그 설정을 따라 작동한다.
위에서 {"object": obj} 등으로 딕셔너리 형태로 context에 데이터를 추가해줬는데, 이렇게 추가하는 정보를 template화해서 다른 곳에서도 공통으로 쓸 수 있게 하는 것이 context_processor다. 즉 아래 설정 정보에 custom한 context_processor를 추가할 수도 있다. 나머지 설정 정보는 DjangoProject 문서를 보면 자세한 내용을 알 수 있다.
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [os.path.join(os.path.dirname(BASE_DIR), "templates")],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
3-3. template, django.contrib
Django template 문법을 사용한 HTML template 페이지이다.
맨 위 extends "admin/actions.html" 부분은 django에서 기본으로 제공하는 template을 상속하여 사용하겠다는 것이다. Pycharm에서 이 부분을 찾아들어가면 아래 사진처럼 djang.contrib 아래 여러 기본 template을 제공하는 것을 볼 수 있다. 이 파일들에 들어가서 {% block ... %}으로 된 구문을 긁어와서 덮어쓰면서 내가 원하는 포맷으로 바꾸면 된다. 예를 들어 아래 코드에서는 block의 이름이 actions-submit인데, 이건 admin/base_site.html에서 이미 정의해놓은 block을 그대로 가져온 뒤, 안에 내용만 button, if문 등으로 새롭게 구성한 것이다.
{% extends "admin/base_site.html" %}
{% block content %}
<div id="container">
<p> </p>
<p>파일 생성 완료 시 다운로드 버튼이 활성화됩니다.(수 분 소요)</p>
<p> </p>
<form action={% url 'v3:simple-model-images-download' object.id %} method="GET">
<input type="submit" class="button" value="압축 파일 생성/새로고침"/>
</form>
{% if not resource_url %}
<form action={% url 'v3:simple-model-images-download' object.id %} method="GET">
<input type="submit" class="button" disabled value="다운로드"/>
</form>
{% else %}
<form action={{ resource_url }}>
<input type="submit" class="button" value="다운로드"/>
</form>
{% endif %}
</div>
{% endblock %}
url과 path_variable
<form> 태그에서 url을 호출할 때, django에서 제공하는 url 호출 형태로 호출하고 뒤에는 object.id 값을 붙였다. 이 object 값은 위 View에서 context로 넘겨줬던 kwargs의 object 값이다. 이 값이 url에서 필요로하는 path_variable로 넘어가서 'base_v1:simple-model-images-download'에 요청을 보내게 된다.
3-4. 비동기 호출과 template 재요청
위에서 호출된 base_v1:simple-model-images-download의 view이다. 로직 진행 후, 비동기 서버에 파일 압축 및 업로드 요청을 보낸다. 파일 압축 및 업로드가 완료되면 resource.file에 압축파일의 url 정보가 기입되도록 서버가 구성되어있다.
비동기 서버 처리 전(요청 직후)
요청을 하자마자는 아직 비동기 서버가 작업을 처리 못했기 때문에, if not resource.file문에 걸려서 다시 template 쪽으로 render 요청을 한다. 그럼 다시 위 template 코드를 보면, resource_url값을 context로 넘겨받아 {% if not resource_url %}에 걸리기 때문에 button은 disabled, 비활성화 상태가 된다.
비동기 서버 처리 후
처리 후 사용자가 다시 압축 파일 생성/새로고침 버튼을 누르면, 다시 아래 코드가 요청되고 else문에 걸려서 resource_url에 download_url값이 들어간채로 template으로 넘어간다. 그럼 다운로드 버튼이 활성화되면서 다운로드를 받을 수 있게 된다.
def download_simple_model_images(request, model_id):
## 복잡한 로직.......
## 비동기 서버에 파일 압축 및 업로드 요청.....
context = {"resource_url": None, "object": model}
if not resource.file:
return render(request,
SimpleModelAdmin.simple_model_images_download_template,
context)
else:
# 압축 파일 가져오기.......
context.update({"resource_url": download_url})
return render(request,
SimpleModelAdmin.simple_model_images_download_template,
context)
'Programming-[Backend] > Django' 카테고리의 다른 글
[TIL] django, MYSQL, postgresql db collation (0) | 2023.02.15 |
---|---|
[TIL] DjangoFilter(DRF filter_bakcends, django-filter filterset_class) (0) | 2023.01.16 |
[TIL] django data migration 데이터 마이그레이션 (0) | 2022.12.17 |
[TIL] FloatField, DecimalField 차이점 / 위경도 표시 소수점과 거리값 (0) | 2022.12.14 |
[TIL] Django prefetch_related, Prefetch 2depth, 모델 필드 정보 조회 (0) | 2022.12.07 |