본문 바로가기

카테고리 없음

Django / generic views.

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가지를 다 가져온 모습을 볼 수 있다.