Day-1(Templates, get_context_data)
기본 Model & View 설정
- 동영상은 youtube에서 '공유-퍼가기(iframe tag로 구성된 url)'를 이용 - embed_code 필드에 입력된다.
models.py
from django.db import models
# Create your models here.
class Video(models.Model):
title = models.CharField(max_length=120)
embed_code = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
view.py - CRUDL을 구성하기 위한 기본 View 구성
# CRUDL
from django.views.generic import CreateView, DetailView, ListView, UpdateView, DeleteView
class VideoCreateView(CreateView):
queryset = Video.objects.all()
class VideoDetailView(DetailView):
queryset = Video.objects.all()
class VideoListView(ListView):
queryset = Video.objects.all()
class VideoUpdateView(UpdateView):
queryset = Video.objects.all()
class VideoDeleteView(DeleteView):
queryset = Video.objects.all()
- generic 기반 Views에 render_to_response(HttpResponse를 담고 있는 메서드)를 포함하기 때문에 별도의 반환값을 지정하지 않아도 된다. Http Method(get, post, put 등..)를 처리할 때, 기능을 추가하거나 변경하고자 할 경우 오버라이딩하는 과정에서 반드시 HttpResponse, render 또는 render_to_response로 반환해야 한다.
- view에서 자주 사용하는 render(django.shortcuts.render) 메서드는 아래와 같이 템플릿, 컨텍스트 등을 HttpResponse에 담아 반환한다.
# django.shortcuts.render
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Return a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
HttpResponse
페이지를 표시할 때 HttpResonse 객체를 요구한다. 없을경우 ValueError 발생.
Templates - settings
# settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(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',
],
},
},
]
- BASE_DIR: 프로젝트의 root 폴더(manage.py가 위치한) 디렉토리
- DIRS: 프로젝트에서 사용될 템플릿의 위치를 지정한다. 위와 같이 구성할 경우 root폴더에 위치한 templates 폴더에 템플릿 파일을 위치시켜야 한다.
- APP_DIRS보다 높은 우선순위를 갖는다.
- APP_DIRS: 각 apps에서 템플릿을 검색할지 여부
- APP_DIRS=True일 경우, template engine에 의해 app에서 사용될 templates 폴더를 해당 app 내에서 검색한다. 일반적으로 templates 하위 폴더에 app의 이름으로 된 폴더를 위치 시킨다.(예: index.html 위치: myapps.templates.myapps.index.html)
- generics.view를 사용할 경우 뷰에 사용되는 모델 이름(Video)과 동작 메서드(list, update, delete, ...)를 접미어로 사용하여 한 번 더 검색
- 예) class VideoListView(ListView) -> video_list
- class VideoUpdateView(UpdateVIew) -> video_update
- APP_DIRS=True일 경우, template engine에 의해 app에서 사용될 templates 폴더를 해당 app 내에서 검색한다. 일반적으로 templates 하위 폴더에 app의 이름으로 된 폴더를 위치 시킨다.(예: index.html 위치: myapps.templates.myapps.index.html)
- 템플릿을 자동으로 검색(아래의 abc directory는 없다고 생각하자)
- OPTIONS - context_processors: context_processor.request & auth는 템플릿에서 request와 user에 대한 처리를 가능토록 지원한다.
<h1>Hello, {{ name }}!</h1>
<p>request: {{ request }}</p>
<p>auth: {{ user }}</p>
Generic view - get_context_data
generic view에서 context를 templates에 전달할 경우 get_context_data 메서드를 오버라이딩 한다.
- render의 매개변수에 context를 담아 templates에 전달하는 것을 get_context_data에서 처리한다.
class VideoListView(ListView):
queryset = Video.objects.all()
def get_context_data(self, *, object_list=None, **kwargs):
context = super(VideoListView, self).get_context_data(**kwargs)
print(context)
return context
# output
{'paginator': None, 'page_obj': None, 'is_paginated': False, 'object_list': <QuerySet
[<Video: django 2.2>, <Video: django 1.11>]>, 'video_list': <QuerySet [<Video: django 2.2>, <Video: django 1.11>]>,
'view': <videos.views.VideoListView object at 0x106292cc0>}
- super(VideoListView, self).get_context_data(**kwargs): VideoListView의 상위 클래스(ListView)의 get_context_data를 불러오고 이를 반환
- 상위 클래스의 get_context_data에는 template에 필요한 몇 가지 변수들을 담고 있다(paginator, object_list 등...).
- 실제 코드에서는 불러온 값에 일부 context값을 추가하여 반환한다.
{{ block.super }}: 부모(extends) 템플릿에 있는 해당 블록의 값을 가져온다.
# base.html
{% block title %}
Srvup
{% endblock %}
# video_list.html
{% extends 'base.html'%}
{% block title %}
Video | {{ block.super }}
{% endblock %}