Django에서 제공하는 generic view는 views.py에 적용할 수 있는 효율적인 웹개발 도구다.
특정 작업에 대해, views.py에서 쉽게 여러 작업을 진행할 수 있게 해놓았다.
그중 ListView는 특정 DB의 정보를 리스트형태로 표시하는데 사용된다. ListView는 제네릭 뷰의 한 종류고, model, template_name을 정의하여 사용한다.
개발 속도를 높여줄 ListView를 만나보자 !
class IndexView(generic.ListView):
model = Question
template_name = "polls/index.html"
#[app_name]/[model_name]_list.html > 보통 이런 형식의 경로를 씀.
context_object_name = "latest_question_list" #index.html에서 받을 때 인식하는 이름
def get_queryset(self):
# 연습 1번
latest_question_list = Question.objects.order_by("-pub_date")[:]
return latest_question_list
여기는 views.py다.
views.py에 클래스를 만들었으니 나의 앱 폴더에 있는 urls.py에가서 urlpatterns를 작성해주자.
urlpatterns = [
# ex: /polls/
path("", views.IndexView.as_view(), name="latest_question_list"), ]
아까 view.py에서 마지막에 latest_question_list를 주었다. 그 후엔
polls폴더 안에있는 index.html이 반응한다.
{% if latest_question_list %}
<h2>Recent Questions</h2>
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
latest_question_list를 확인하고나서 이 html 태그대로 화면에 보여준다.
그런데 아까는 return 다음에
latest_question_list 하나만 넘겨줬는데, 좀 더 넘겨주고 싶을 수도 있다.
def get_context(request):
# 연습 1번
latest_question_list = Question.objects.order_by("-pub_date")[:]
# 연습 2번
top_questions = Question.objects.annotate(total_votes=Sum('choice__votes')).order_by('-total_votes')[:5]
# 연습 3번
unvoted_questions = Question.objects.annotate(total_votes=Sum('choice__votes')).filter(total_votes=0)
context = {
"latest_question_list": latest_question_list,
"top_questions": top_questions,
"unvoted_questions": unvoted_questions, }
return render(request, "polls/index.html", context)
이렇게 넘겨주는 것이, Listview에서는 안된다.
이렇게 하려면 request를 같이 넘겨줘야되는데, get_queryset 메서드는 기본적으로 self만 인자로 받는다.
class IndexView(generic.ListView):
model = Question
#[app_name]/[model_name]_list.html > 보통 이런 형식의 경로를 씀.
template_name = "polls/index.html"
context_object_name = "latest_question_list" #index.html에서 받을 때 인식하는 이름
def get_queryset(self):
# 연습 1번
latest_question_list = Question.objects.order_by("-pub_date")[:]
# 연습 2번
top_questions = Question.objects.annotate(total_votes=Sum('choice__votes')).order_by('-total_votes')[:5]
# 연습 3번
unvoted_questions = Question.objects.annotate(total_votes=Sum('choice__votes')).filter(total_votes=0)
return latest_question_list
def get_context_data(self, **kwargs):
# 부모 클래스의 get_context_data를 호출하여 기본 컨텍스트를 가져옵니다.
context = super().get_context_data(**kwargs)
# 추가 컨텍스트를 정의합니다.
context['top_questions'] = Question.objects.annotate(total_votes=Sum('choice__votes')).order_by('-total_votes')[:5]
context['unvoted_questions'] = Question.objects.annotate(total_votes=Sum('choice__votes')).filter(total_votes=0)
return context
이럴때 추가적으로 데이터를 넘기고 싶다면, 이렇게 IndexView클래스의 get_context_data 메서드를 가져올 수 있다. context안에 저렇게 데이터를 담아서 추가해주고나서 넘겨주면 된다.
{% if latest_question_list %}
<h2>Recent Questions</h2>
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No recent questions are available.</p>
{% endif %}
{% if top_questions %}
<h2>Top Questions</h2>
<ul>
{% for question in top_questions %}
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No top questions are available.</p>
{% endif %}
{% if unvoted_questions %}
<h2>Unvoted Questions</h2>
<ul>
{% for question in unvoted_questions %}
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No unvoted questions are available.</p>
{% endif %}
그리고나서 index.html에서
저 3개 변수에 대해서 조건문을 통해 처리를 해준다.
그러면 이렇게 3가지를 다 가져온 모습을 볼 수 있다.