|
|
| 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 /> |
장고! 웹 프레임워크! 틀:장고
- 장고:개요
- 장고:웹페이지설계
- 장고:앱
- 장고:url
- 장고:model
- 장고:DB
- 장고:모델 필드
- 장고:모델의 변경
- 장고:view
- 장고:클래스형 뷰, 제네릭 뷰
- 장고:view 각종 기능
- 장고:template
- 장고:static. 정적파일 사용하기
- 장고:CSS 사용하기
- 장고:JS 사용하기
- 장고:글꼴 사용
- 장고:부트스트랩
- 장고:media. 미디어 파일 사용하기
- 장고:관리자페이지
- 장고:settings.py
- 장고:기능구현
- 장고:회원관리
- 장고:유저
- 장고:커스텀 유저
- 장고:소셜로그인
- 장고:입력받기
- 장고:저장된 내용 활용하기
- 장고:변수 내보내기
- 장고:글쓰기
- 장고:페이징(페이지나누기)
- 장고:답변쓰기(댓글쓰기)
- 장고:추천,즐겨찾기
- 장고:새글(최신글) 나타내기
- 장고:썸머노트 설치
- 장고:네비게이션 바 만들기
- 장고:검색기능
- 장고:카테고리 만들기
- 장고:사진 올리기
- 장고:파일 업로드
- 장고:이메일app 만들기
- 장고:매직 그리드
- 장고:웹서비스
- 장고:Git
- 장고:리눅스에 올리기
- 장고:우분투에 올리기(nginx 사용)
- 장고:도커로 올리기
- 장고:서버 옮기기
- 장고:팁
작정하고 장고의 코드를 참고해 살펴보는 게 좋겠다.
클래스 뷰를 사용할 때 특정한 기능이 다른 뷰로 분리되어 있을 때. 예컨대, DetailView에선 form이 없기 때문에 댓글을 쓸 수가 없다. 이땐 다중상속을 받아 기능을 구현할 수 있다.
class 뷰이름(DetailView, FormMixin):
form_class = 폼이름
...
def form_valid(self, form):
...
writer = self.request.user
return super().form_valid(form)
위와 같이 Mixin으로 없는 기능을 가져다 넣어 사용할 수 있다.
여러 오브젝트를 다루기 위한 믹스인.
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)
본문과 리스트를 동시에 띄우기 위한 작업이다.
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('모델명') 형태로 쓰면 필터에 걸린 것들 중 해당 모델에 해당하는 것을 가져온다.(제한적으로 쓰일 것 같지만, 강력하고 어려운 개념이네;)
그럼 이를 불러오려는 모델처럼 다룰 수 있다.
게시글목록 중 글 자체에 대한 것과, 검색부분과... 다 따로만드는 게 좋을 듯하다. 글 자체에 대한 건 즐겨찾기 한 문제들을 불러올 수 있잖아. 옵션에 따라 글부분만 달리 나타낼 수도 있고.