장고:클래스형 뷰, 제네릭 뷰: 두 판 사이의 차이

학교의 모든 지식. SMwiki
둘러보기로 이동 검색으로 이동
 
3번째 줄: 3번째 줄:
작정하고 장고의 코드를 참고해 살펴보는 게 좋겠다.
작정하고 장고의 코드를 참고해 살펴보는 게 좋겠다.


<br />
== 옮기다 말았음. ==
=클래스형 뷰=
기본적으로 뷰는 함수로 만들지만, 코드가 길어지면 클래스형 뷰가 필요하다. 중급자 이상으로 넘어가기 위해선 필수적으로 숙달해야 할 내용.
 
함수형 뷰보다 재사용하기가 쉬워 고급사용자가 될수록 더 많이 사용하게 되는 형태.
=제네릭 뷰=
View는 기본적으로 함수로 만들지만, 이미 자주 쓰이는 기능을 또 새로이 만들어야 할까? 이미 개발된 뷰가 있다.이를 제네릭뷰라 부르며, 클래스형으로 구성되어 있다.
 
장고에서 제공하는 뷰이다.
 
크게 4가지 분류의 클래스뷰가 있다. CRUD 기능을 제공하게끔. 장고의 특성이다. CRUD 구현이 쉬워.[일반 뷰에서도 이런 틀로 정리해보자.]
{| class="wikitable"
|+
!기능
!뷰 이름
!비고
!
|-
|Create
|CreateView
|form_class = 사용할 폼이름
|
|-
|Read
|DetailView
|
|
|-
|Update
|UpdateView
|기본적으로 CreateView와 같은 속성을 갖는다.
|
|-
|Delete
|DeleteView
|
|
|}
Class형 view가 편하다곤 하지만.. 그 강점은 장고가 업데이트 되 때에 일관성 있게 작동할 가능성을 높여준다는 것 외엔.. 딱히 모르겠다. 사실, 엄청 편리한 것도 모르겠고.. 공부를 위해선, 전체작동방식의 느낌을 알기 위해선 함수를 처음부터 짜는 view가 더 좋은 듯하다.(장고 자체를 더 공부해야 한다는 점에서 별로다; 그럴바엔 파이썬 자체를 더 다뤄보지!)
 
내부적으로 어떻게 작동하는지 알기 어려워, 도리어 혼란스러울 때도 있다.
 
<nowiki>#</nowiki>제네릭 뷰에서 데이터를 탬플릿에 전달할 때 리스트 이름이 지정되어 있는데, 리스트 이름을 바꾸려면 get_queryset함수 안에 이 변수를 넣는다.(글쓰기 기능구현 참조)
 
context_object_name='바꿀리스트명'
 
기본적으로 짧기 때문에 urls.py 안에 바로 기입해줘도 가독성에 무리가 적다.
==제네릭 뷰의 변수==
{| class="wikitable"
|+
!변수
!설명
!사용예
|-
|fields
|어떤 필드를 기입할지.
|fields=['subject', 'text']
|-
|tempalte_name
|기본 탬플릿 말고 따로 지정할 때
|template_name='app/list.html'
|-
|success_url
|함수의 기능이 성공했을 때 어떤 url로 보낼지 지정
|success_url='/app/'
|-
|model
|어떤 모델에 대한 뷰인지.
|model = User
|-
|context_object
|불러온 모델명을 탬플릿에 보낼 때 그대로 보내는데, 다른 이름을 사용하고 싶을 때
|context_object = target_user
|-
|
|
|
|}
self.get_object() : 사용하고 있는 모델의 객체를 가져온다.
 
===함수===
{| class="wikitable"
!함수
!설명
!사용예
|-
|get_success_url
|성공 후 진행할 작업을 여기에 담는다.
|<syntaxhighlight lang="python">
def get_success_url(self):  # 기존 함수를 덧쓴다. 작성 후에 해당 글을 보여주게끔.
    return reverse('pool:detail', kwargs={'pk': self.object.question.pk})
</syntaxhighlight>
|-
|form_valid
|폼이 적절할 때 실행할 함수.
|<syntaxhighlight lang="python">
def form_valid(self, form):  # 폼에 이상이 없으면 실행.
    temp = form.save(commit=False)  # 임시 저장. 폼 외의 다른 내용을 조작하고 싶을 때 사용한다.
    조작
    temp.save()  # 최종 저장
    return super().form_valid(form)
</syntaxhighlight>
|}
 
==ListView==
많은 객체들을 한번에 보여주기 위한 뷰. 기본 형태는 다음과 같다.<syntaxhighlight lang="python">
class 뷰이름(ListView):
    model = 사용할 모델
    context_object_name = '모델을 표현할 이름'
    template_name = '탬플릿 경로'
    paginate_by = 몇 개 단위로 보여줄 것인가.
</syntaxhighlight>이렇게 만들면 객체리스트가 <code>모델명_list</code> 형태로 탬플릿에 전달된다.
 
===pagination===
객체가 너무 많을 때 한 화면에 모든 것을 보여줄 순 없다. 이런 문제를 해결하기 위해 한 화면에 보여줄 객체의 갯수를 정해 페이지화 해야 한다.
 
혹은... infinite scroll 형식으로 만들 수도 있지만 이를 위해선 자바스크립트 사용이 필요하다.
 
페이지 버튼은 탬플릿에 따로 기입한다.
 
다음과 같은 형태로 page 변수를 get 방식으로 넘겨준다.<syntaxhighlight lang="html+django">
<a href="{% url '앱:인덱스' %}?page={{ page_obj.number}}">{{ page_obj.number }}</a>
</syntaxhighlight>페이지 버튼만 따로 떼어 html을 만든 후 include를 하기도 한다.


==유의사항==
===Mixin[따로 목차를 분류해야겠네;]===
===url.py 에서 사용할 때===
제네릭 뷰를 사용할 때 urls.py에서 어떤 변수명을 사용하는 게 아니라, 변수명들이 예약되어 있다.
{| class="wikitable"
|+예약된 변수명
!변수
!설명
|-
|<int:pk>
|기본키를 받아들이는 변수
|-
|
|
|-
|
|
|}
====함수명 뒤에 .as_view()를 붙인다.====
그냥 view를 사용할 땐 함수명을 쓰면 됬지만, 제네릭 뷰에선 마지막에 .as_view()를 붙여주어야 한다.
===탬플릿에서 사용할 때===
ListView에선 모델명_list 라는 변수로 탬플릿에 전달된다.
 
DetailView에선 object라는 변수로 모델이 탬플릿에 전달된다.
 
<br />
 
=Mixin[따로 목차를 분류해야겠네;]=
클래스 뷰를 사용할 때 특정한 기능이 다른 뷰로 분리되어 있을 때. 예컨대, DetailView에선 form이 없기 때문에 댓글을 쓸 수가 없다. 이땐 다중상속을 받아 기능을 구현할 수 있다.<syntaxhighlight lang="python">
클래스 뷰를 사용할 때 특정한 기능이 다른 뷰로 분리되어 있을 때. 예컨대, DetailView에선 form이 없기 때문에 댓글을 쓸 수가 없다. 이땐 다중상속을 받아 기능을 구현할 수 있다.<syntaxhighlight lang="python">
class 뷰이름(DetailView, FormMixin):
class 뷰이름(DetailView, FormMixin):
165번째 줄: 17번째 줄:
<br />
<br />


=== MultipleObjectMixin ===
===MultipleObjectMixin===
여러 오브젝트를 다루기 위한 믹스인.<syntaxhighlight lang="python">
여러 오브젝트를 다루기 위한 믹스인.<syntaxhighlight lang="python">
class 뷰이름(DetailView, MultipleObjectMixin):
class 뷰이름(DetailView, MultipleObjectMixin):
178번째 줄: 30번째 줄:
<br />
<br />


== RedirectView ==
==RedirectView==
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
class 뷰이름(RedirectView):
class 뷰이름(RedirectView):
191번째 줄: 43번째 줄:
</syntaxhighlight>
</syntaxhighlight>


= 구독 기능 =
=구독 기능=
찬찬히 보면서 옮기자.. 문제를 풀었는가 여부도 이걸로 구현 가능할듯.
찬찬히 보면서 옮기자.. 문제를 풀었는가 여부도 이걸로 구현 가능할듯.


204번째 줄: 56번째 줄:
filter(user=user, project=객체명) 형태로 일치하는지 여부만 찾으면 된다.
filter(user=user, project=객체명) 형태로 일치하는지 여부만 찾으면 된다.


=== Fieldlookup ===
<br />
filter 안에서 언더바 2개로 작동하는 장고의 기능.
===필터 이후 처리===
 
값__in 은 SELECT ... WHERE 값 IN ...; 과 대응한다.
 
조금 더 복잡한 DB query를 사용하기 위한 기능이다.
 
장고 도큐먼트를 보면.... 나온다.
 
=== 필터 이후 처리 ===
필터링으로 구독관계 객체를 불러왔다곤 하지만, 이것이 구독한 객체를 보여주지 않는다. 이를 위해 .values_list('모델명')이 쓰인다.
필터링으로 구독관계 객체를 불러왔다곤 하지만, 이것이 구독한 객체를 보여주지 않는다. 이를 위해 .values_list('모델명')이 쓰인다.


219번째 줄: 63번째 줄:


그럼 이를 불러오려는 모델처럼 다룰 수 있다.
그럼 이를 불러오려는 모델처럼 다룰 수 있다.
 
===아이디어===
=== 아이디어 ===
게시글목록 중 글 자체에 대한 것과, 검색부분과... 다 따로만드는 게 좋을 듯하다. 글 자체에 대한 건 즐겨찾기 한 문제들을 불러올 수 있잖아. 옵션에 따라 글부분만 달리 나타낼 수도 있고.
게시글목록 중 글 자체에 대한 것과, 검색부분과... 다 따로만드는 게 좋을 듯하다. 글 자체에 대한 건 즐겨찾기 한 문제들을 불러올 수 있잖아. 옵션에 따라 글부분만 달리 나타낼 수도 있고.
<br />
<br />

2021년 6월 25일 (금) 14:52 기준 최신판

장고! 웹 프레임워크! 틀:장고

  1. 장고:개요
  2. 장고:웹페이지설계
    1. 장고:앱
    2. 장고:url
    3. 장고:model
      1. 장고:DB
      2. 장고:모델 필드
      3. 장고:모델의 변경
    4. 장고:view
      1. 장고:클래스형 뷰, 제네릭 뷰
      2. 장고:view 각종 기능
    5. 장고:template
    6. 장고:static. 정적파일 사용하기
      1. 장고:CSS 사용하기
      2. 장고:JS 사용하기
      3. 장고:글꼴 사용
      4. 장고:부트스트랩
    7. 장고:media. 미디어 파일 사용하기
  3. 장고:관리자페이지
  4. 장고:settings.py
  5. 장고:기능구현
    1. 장고:회원관리
    2. 장고:유저
    3. 장고:커스텀 유저
    4. 장고:소셜로그인
    5. 장고:입력받기
    6. 장고:저장된 내용 활용하기
    7. 장고:변수 내보내기
    8. 장고:글쓰기
    9. 장고:페이징(페이지나누기)
    10. 장고:답변쓰기(댓글쓰기)
    11. 장고:추천,즐겨찾기
    12. 장고:새글(최신글) 나타내기
    13. 장고:썸머노트 설치
    14. 장고:네비게이션 바 만들기
    15. 장고:검색기능
    16. 장고:카테고리 만들기
    17. 장고:사진 올리기
    18. 장고:파일 업로드
    19. 장고:이메일app 만들기
    20. 장고:매직 그리드
  6. 장고:웹서비스
    1. 장고:Git
    2. 장고:리눅스에 올리기
    3. 장고:우분투에 올리기(nginx 사용)
    4. 장고:도커로 올리기
  7. 장고:팁

작정하고 장고의 코드를 참고해 살펴보는 게 좋겠다.

옮기다 말았음.[편집 | 원본 편집]

Mixin[따로 목차를 분류해야겠네;][편집 | 원본 편집]

클래스 뷰를 사용할 때 특정한 기능이 다른 뷰로 분리되어 있을 때. 예컨대, DetailView에선 form이 없기 때문에 댓글을 쓸 수가 없다. 이땐 다중상속을 받아 기능을 구현할 수 있다.

class 뷰이름(DetailView, FormMixin):
    form_class = 폼이름
    ...
    def form_valid(self, form):
        ...
        writer = self.request.user
        return super().form_valid(form)

위와 같이 Mixin으로 없는 기능을 가져다 넣어 사용할 수 있다.


MultipleObjectMixin[편집 | 원본 편집]

여러 오브젝트를 다루기 위한 믹스인.

class 뷰이름(DetailView, MultipleObjectMixin):
    form_class = 폼이름
    ...
    paginate_by = 10
    
    def get_context_data(self, **kwargs):
        object_list = 모델.objects.filter(필터링조건)
        return super(뷰이름,self).get_context_data(object_list=object_list, **kwargs)

본문과 리스트를 동시에 띄우기 위한 작업이다.


RedirectView[편집 | 원본 편집]

class 뷰이름(RedirectView):
    
    
    def get_redirect_url(self, *args, **kwargs):
        return 보낼 주소
        
    def get(self, request, *args, **kwargs):
        object = get_object_or_404(모델, pk=키값)

구독 기능[편집 | 원본 편집]

찬찬히 보면서 옮기자.. 문제를 풀었는가 여부도 이걸로 구현 가능할듯.

유저와 프로젝트를 포린키로 가져온다.

모델작성

class 모델명(models.Model):
    class Meta:
        unique_together = ('속성1', '속성2')

이 둘의 조합은 오직 하나만 존재하도록 설정한다. 이 모델을 filter로 불러와 유저와 객체가 일치하는 것을 찾아 구독관계를 찾곤 한다.

filter(user=user, project=객체명) 형태로 일치하는지 여부만 찾으면 된다.


필터 이후 처리[편집 | 원본 편집]

필터링으로 구독관계 객체를 불러왔다곤 하지만, 이것이 구독한 객체를 보여주지 않는다. 이를 위해 .values_list('모델명')이 쓰인다.

객체 = ...filter(조건).values_list('모델명') 형태로 쓰면 필터에 걸린 것들 중 해당 모델에 해당하는 것을 가져온다.(제한적으로 쓰일 것 같지만, 강력하고 어려운 개념이네;)

그럼 이를 불러오려는 모델처럼 다룰 수 있다.

아이디어[편집 | 원본 편집]

게시글목록 중 글 자체에 대한 것과, 검색부분과... 다 따로만드는 게 좋을 듯하다. 글 자체에 대한 건 즐겨찾기 한 문제들을 불러올 수 있잖아. 옵션에 따라 글부분만 달리 나타낼 수도 있고.