[django] View 1 - Gegeric View Overriding

Hyeseong·2020년 12월 22일
0

django

목록 보기
14/35

Generic View Overriding

어떤 Generic View를 선택할지 결정했다면, 해당 뷰에 정의된 속성(변수)과 메소드를 확인하여 어떤걸 오버라이딩 할지 정해야해요.

attribute overriding

model

기본 뷰(View, TemplateView, RedireceView) 3개와 FormView를 빼고는 모든 Generic View에서 사용하는 속성이에요.
말 그대로 모델 지정 작업이에요.

model 대신 queryset 속성을 지정할 수 있어요.

  • model = Bookmark
  • queryset = Bookmark.objects.all()
    위 2가지 표현은 동일해요.

queryset

기본 뷰(View, TemplateView, RedireceView) 3개와 FormView를 빼고는 모든 Generic View에서 사용하는 속성이에요.
QuerySet 객체를 지정해요.

queryset > model / 두개가 모두 적혀있으며 queryset이 적용됨.

template_name

모든 Generic View에서 사용하는 속성.
템플릿 파일명을 문자열로 지정.

context_object_name

기본 뷰(View, TemplateView, RedireceView) 3개와 FormView를 빼고는 모든 Generic View에서 사용하는 속성이에요. template file에서 사용할 context_variable 이름을 지정함.

paginate_by

ListView와 날짜 기반 뷰에서 사용함. 페이지당 몇개를 출력할지 int로 지정해요.

date_field

날짜 기반 뷰에서 기준이 되는 필드 지정!
이 필드를 기준으로 year/month/day를 검사해요.
해당 field의 type은 DateField or DateTimeField에요.

make_object_list

YearArchiveView 사용 시 해당 년에 맞는 객체들의 리스트를 생성할지 여부를 지정해요.

True면 객체들의 리스트를 만들고 그 리스트를 템플릿에서 사용할 수 있어요.
'False'면 queryset속성에 None이 할당되요.

form_class

FormView, CreateView, UpdateView에서 사용함. 폼을 만드는 데 사용할 클래스를 지정함.

initial

FormView, CreateView, UpdateView에서 사용
form에 사용할 초기 데이터를 사전형 {} 으로 지정해요.

fields

CreateView, UpdateView에서 사용. 폼에 사용할 필드 지정
어찌보면 ModelForm 클라쓰의 Meta.fields 속성과 동일한 의미임.

success_url

FormView, CreateView, UpdateView, DeleteView에서 사용.
폼에 대한 처리가 성공한 후 redirect될 URL 지정

Method Overriding

get_queryset()

기본 뷰(View, TemplateView, RedireceView) 3개와 FormView를 빼고는 모든 Generic View에서 사용하는 메소드에요.

출력 객체를 검색하기 위한 대상 QuerySet 객체 or 출력대상인 객체 리스트를 반환함.
default는 queryset 속성값 반환.
queryset 속성이 지정되지 않은 경우는 모델 매니저 클래스의 all() 메소드를 호출해서 QuerySet 객체를 생성하고 이를 반환해요.

get_context_data(**kwargs)

TemplateView를 포함해 모든 제네릭 뷰에서 사용하는 메소드에요. 템플리에서 사용할 컨택스트 데이터를 반환해요.

form_valid(form)

FormView, CreateView, UpdateView에서 사용해요. get_success_url() 메소드가 반환하는 URL로 redirect를 실행해요

example

일반 case1

model, template_name, context_object_name 속성이 오버라이딩 되있네요.
대~~~개 오버라이딩하는 늘상 만나고 사용하는 녀석들이조?
아! 또 페이징 기능(1페이지, 2페이지)을 활성하 했네요.(페이지당 2개의 레코드 출력)

testapp/urls.py

# 생략
	path('test/', views.TestPostLV.as_view(), name='test_post'),
]

test/views.py

class TestPostLV(ListView):
	model = Post
    template_name = 'test/post_all.html'
    context_object_name = 'posts'
    paginate_by = 2

queryset 속성

위의 case1을 수정해서 리스트를 모두 보여주지 않고 only 5개를 보여주고 싶다면?!
그때 queryset 속성을 사용하면. 금상첨화조?!
백문이 불여일타!

class TestPostLV(ListView):
	#model = Post
    queryset = Post.objects.all()[:5]
    template_name = 'test/post_all.html'
    context_object_name = 'posts'
    paginate_by = 2

특히 눈에 띄는점은 [:5] 요건데요. 파이썬 기초 문법편의 index와 슬라이싱을 이용하여 원하는 만큼 해당 값을 나타나게 하는 거조?

get_queryset()

포스트 글에 특정 단어가 들어 있는 객체들만 보여주고 싶다면? 그런 로직은 구현은 아래와 같이 하면되요.
특정 단어는 URL에 지정하는 것으로 변경해요.

test/urls.py

#생략
	#path('test/', views.TestPostLV.as_view(), name='test_post'),
    #ex. /blog/test/word/
    path('test/<str:word>/', views.TestPostLV.as_view(), name='test_post'),

test/views.py

# 생략
class TestPostLV(ListView):
	model = Post # 정적
    #queryset = Post.objects.all()[:5] # 동적
    template_name = 'test/post_all.html'
    context_objects_name = 'posts'
    paginate_by = 2
    
    def get_query_set(self):
    	return Post.objects.filter(Q(content_icontains=self.kwargs['word'])).distinct()

인터넷에서 검색 기능을 구현할 때 유용하게 사용하는 Q객체를 사용해서 검색하고 있어요. 여기서는 example에서 URL에서 지정함으로써, 동적으로 출력 대상을 변경하고 있다는거~

get_query_set메소드의 filter를 이용한 Q객체 없이 그냥 기존의 queryset 속성으로는 안되겠쥬?

data출력을 유연하게 하고 싶은경우

  • queryset 속성 오버라이딩
  • get_queryset() 메소드 오버라이딩
  • queryset은 출력 개수를 조절
  • get_queryset()은 특정 data의 표현까지 control하여 출력 가능하게 함.

Key Point!!

model 속성, gueryset 속성, get_queryset() 메소드 3가지는 동일한 역할이므로 한가지만 사용하면 되요.

template_name 속성

템플릿 처리를 어떻게 오버라이딩 해서 하는지 알아볼게요.

class TestPostLV(ListView):
	#model = Post
    #queryset = Post.objects.all()[:5]
    #template_name = 'test/post_all.html'
    template_name = 'test/post_test.html'
    context_object_name = 'posts'
    paginate_by = 2
    
    def get_query_set(self):
    	return Post.objects.filter(Q(content_icontains=self.kwargs['word'])).distinct()

템플릿 변경을 직접 해보종~

 # 생략

{% block content %}

	<h1> Blog List - Test</h1> 
	<br>
...
...
{% endblock %}

get_context_data()

View --> Template 넘겨주는 context data를 추가, 변경할 수 있어요.
아시다시피 generic view는 default 이름으로 사용하는 변수가 있조?

  • ListView - object_list
  • DetailView - object

만약 위의 것 말고 추가로 지정하고 싶은게 있다면??
get_context_data()를 오버라이딩 하는것이 방법이에요.

만일 URL에 지정된 검색 단어를 페이지에 출력하고자 한다면, 다음 코드처럼 검색 단어를 컨텍스트 객체에 담아서 테믈릿 파일에 넘겨주면 되요. get_context_data() 메소드는 context data를 새로 구성하는 메소드에요.

test/views.py

class TestPostLV(ListView):
	model = Post # 정적
    #queryset = Post.objects.all()[:5] # 동적
    template_name = 'test/post_all.html'
    context_objects_name = 'posts'
    paginate_by = 2
    
    def get_query_set(self):
    	return Post.objects.filter(Q(content_icontains=self.kwargs['word'])).distinct()
    
    def get_context_data(self, **kwargs):
    	context = super().get_context_data(**kwargs)
        context['SearchWord'] = self.kwargs['word']
        return context
    

Template 파일에서 사용할 context variable은 SearchWord로 지정하고, 이 변수에 클라이언트가 입력한 검색 단어를 할당했어요. 그리고 기존 context data는 변경없이 사용하기 위해 super() 함수로 상위 클래스의 메소드를 호출한다는점에 유의!

View에서 넘어온 data를 출력하기 위해서 post_test.html 파일의 제목줄을 다음과 같이 수정할게요.
{{ SearchWord }} 컨텍스트 변수를 사용할게요.

<h1> Blog List - contains the word '{{ SearchWord }}'</h1>
profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글