1. admin
-필드 분리: fieldsets = []
-필드 접기: fieldset = ('Date Information', {'fields':['pub_date'], 'classes':['collapse']})
-ForeignKey: Question 화면에서 Choice 보기
=> Inline 클래스 추가
class ChoiceInline(admin.StackedInline):
# 줄로 나타내고싶으면 TabularInline
model=Choice
extra = 2 #기존 데이타 이외의 엑스트라 공백 칸 수
=> QuestionAdmin 클래스에 inlines 변수 추가
...
inlines = [ChoiceInline]
...
-list에 보여주는 컬럼 지정
list_display = (), # 튜플 형식 (뒤에 , 찍어야함)
-list_filter: 필터하기
list_filter = ()
=> 필터 형식에 따라 장고가 자동으로 생성
-search_fields
search_fields = [] or ()
-템플릿 수정
장고의 기본 admin 템플릿 파일을 프로젝트로 복사 후 수정 => settings.py 파일에 등록
...django/contrib/admin/templates/admin 하위의 base_site.html 이다.
=> templates/admin (프로젝트의)에 복사
=> settings.py에 TEMPLATES의 DIRS에 [os.path.join(BASE_DIR, 'templates')] 추가
*장고 path 찾기
python -c "
import sys
sys.path = sys.path[1:]
import django
print(django.__path__)"
'/home/seul/.pyenv/versions/djangostudy/lib/python3.6/site-packages/django'
*문제: 프로젝트 하위 디렉토리의 base_site.html을 변경하였는데 아무런 변화가 없ㅇ므
=> 그냥 해결됨
장고가 html을 찾는 순서는
-폴더 안의 templates를 보고, 없다면
-installed_apps에 있는 디렉토리를 순서대로 따라가며 찾는다
=> 이 loader를 활성화 시키려면 APP_DIRS: True로 지정
2. 장고 파이썬 쉘로 데이터 조작하기
-복잡한 데이터 처리 가능
$python manage.py shell # 장고 파이썬 쉘 접속
CRUD로 설명
1) Create => 내부적으로 SQL의 INSERT문 실행
객체를 생성한 후 save() 전까지는 메모리에서만 변경, 반드시 save() 해야함
2) Retrive =>
데이터 조회를 위해서 QuerySet 객체 사용
QuerySet: 데이터베이스 테이블에서 꺼내온 객체 콜렉션, 필터를 사용하여 조건에 맞는 레코드 추출
objects 객체를 사용하여 QuerySet을 얻음 => objects: 테이블 정보를 담고 있는 객체
>> Question.objects.all() # Question 테이블.레코드.모두
조건을 사용하려면 filter(), exclude()
한개만 검색하는 경우에는 get
slicing 문법을 활용해서 [:5]같이 할수있음 => 리스트를 반환 (OFFSET, LIMIT - SQL 용어로는)
3) Update => 데이터 수정
그냥 필드 속성값 수정 후 save(), 여러개를 수정할 때는 update() 메소드
q.question_tedt = "making change" #이렇게
4) Delete => 데이터 삭제
Question.objects.filter(pub_date__year=2000).delete()
Question.objects.all().delete() 로 모두 삭제 가능하다.
3. 템플릿 시스템
-템플릿에서의 for, if: 템플릿 시스템에서만 사용되는 고유의 문법,
템플릿 코드 => 렌더링 => 템플릿 파일로 해석(HTML, CSV 등 텍스트 파일)
*템플릿 변수
{{ variable }}
-. (dot)은 파이썬 언어와 다름.
ex) foo.bar
=> foo가 dict 타입인지 확인. 맞다면 foo['bar']
=> foo의 속성. 있다면 foo.bar
=> foo가 리스트인지 확인. 맞다면 foo[bar]
*템플릿 필터
템플릿 변수에 필터를 적용하여 변수의 출력 결과 변경
-파이프 문자 (|) 사용
{{ name|lower }} # 모두 소문자로 바꿔주는 필터
-필터를 체인으로 연결 가능.
{{ text|escape|linebreaks }} # text 중에 특수문자를 escape, 그 결과 스트링에 HTML <p> 태그를 붙여줌
-인자를 가질 수도 있음
{{ bio|truncatewords:30 }} # bio 변수값 중 앞의 30개 단어만 보여주고 줄바꿈 문자를 없애줌
{{ list|join:" // " }} # 인자에 빈칸이 있는 경우 따옴표로 묶기 (?)
{{ value|default:"nothing" }} # 변수값이 False일 경우 'nothing'으로 표시
{{ value|length }}
{{ value|striptags }} # 변수값에서 HTML 태그를 없애줌 (?)
{{ value|pluralize }} # 복수 쩝미사 필터
{{ value|pluralize:"es" }}
{{ value|pluralize:"y, ies" }}
{{ value|add:L"2" }} # 더하기, 타입에 따라 결과가 달라질 수 있음
{{ first|add:second }} # 타입의 인자를 integer라고 간주하고 덧셈 => 실패하면 문법에 따라 더하기 (리스트, string 등...)
(https//docs.djangoproject.com/en/1.10/ref/templates/builtins/) 참고
*템플릿 태그
-{% tag %}의 형식
*{% for %}
-forloop.counter: 현재까지 루프 실행한 루프 카운트(1부터)
-forloop.counter0: 0부터 카운트
-forloop.revcounter: 끝에서 현재가 몇인지 카운트 (1부터)
-forloop.revcounter0: 0부터
-forloop.first: 루프에서 첫번째 실행시 True
-forloop.last: 루프에서 마지막 실행시 True
-forloop.parentloop: 중첩된 루프에서 현재 루프 바로 상위의 루프
*{% if %}: 변수 평가 후 True면 아래 문장 표시
-if 태그에 필터와 연산자 사용 가능, str 반환하므로 산술 연산이 안되고 length만 가능
{% if athlete_list|length > 1 %}
and, or, not, and not, ==, !=, in 등의 연산자 사용 가능
*{% csrf_token %}:
POST 방식의 oform 사용하는 코드에서 공격 방어위해 사용
<form action="." method="POST">{% csrf_token %}
와 같이 폼엘리먼트 첫줄 다음에 넣어주면 됨
# CSRF 공격(Cross-Site Request Forgery): 사이트간 요청 위조 공격
*{% url %}: 소스에 URL 하드코딩을 방지하기 위해서
=> 원하는 URLconf 모듈만을 참조 가능
{% url 'namespace:view-name" arg1 arg2 %}와 같은 방식으로 사용
-namespace: urls.py의 include 함수에서 정의한 namespace
-argN: 뷰함수에서 사용하는 인자, 빈칸으로 여러개 구분
*{% with %} : 특정 값을 변수에 저장
{% with total=business.employees count %}
{{ total }} people works at business
{% endwith %}
=> total은 with 구문 내에서만 유효, 부하를 줄여주는 효과
*{% load %}: 사용자 정의 태그 및 필터 로딩
=> 개발자가 필요에 따라 스스로 정의하여 사용 가능
{% load somelibrary package.otherlibrary %} 와 같이 사용
=> somelibrary.py 파일 및 package/otherlibrary.py에 정의된 태그, 필터 로딩
**템플릿 주석
-한줄 주석문: {# #} 형식
-여러줄: {% comment "optional note %}
{% endcomment %}
**HTML 이스케이프
디폴트로 HTML에 사용되는 예약 문자들을 의미르 제거한 문자로 변경해주는 기능
< : < (less than)
>: > (greater than)
': '
" : "
& : & (ampersand)
이외의 자동 이스케이프 비활성화시키는 방법
-safe 필터 사용: {{date|safe }}
-{% autoescape off %}
{% endautoescape %}
**템플릿 상속: 코드 재사용, 룩앤필 일관성있게. 어렵지만 강력한 기능
{% block title %} {% endblock %} 방식으로 사용
자식 템플릿에서 {% extends 'base.html' %}을 쓰고 block문을 이어서 사용
다음 단게를 따라서 해라
1). 사이트 전체의 룩앤필을 담은 base.html
2). 하위의 섹션별 스타일을 담은 base_news.html 등을 만듬, 1단계 base.html을 상속
3). 개별 페이지의 템플릿을 만들어서 2단계 템플릿을 상속
4. 폼 처리하기: 장고의 폼 기능
**HTML에서의 폼: input 엘리먼트 외에도 actoin 속성(폼 데이터를 어디로 보낼지)고ㅑㅏ method 속성(어떤 HTTP 메소드로 보낼지)을 정해줘야함 => GET, POST뿐
=> 장고는 이중에서 POST 방식만 사용
**장고의 폼 기능 (??)
*장고는 폼처리를 위한 3가지 기능 제공
-폼 생성에 필요한 데이터를 폼 클래스로 구조화
-폼 클래스의 데이터를 렌더링하여 HTML 폼 만들기
-사용자로부터 제출된 폼과 데이터를 수신, 처리
폼도 결국은 템플릿의 일부 => 템플릿 코드에 포함되서 렌더링 절차, 3가지 과정
=> 렌더링할 객체를 뷰로 가져오기(데이터베이스에서 객체 추출)
=>그 자체를 템플릿 시스템에게 넘겨주기
=>템플릿 문법을 처리하여 HTML 마크업 언어로 변환
: 폼 객체에는 데이터가 없을 수도 있음(사용자가 데이터를 채우는게 보통)
데이터가 없는 폼: unbound form => 비어있거나 default값
데이터가 있는 폼: bound form => 제출된 데이터를 갖고 유효성 검사를 하는데 사용
*폼클래스로 폼 생성하기 => 폼도 클래스로 정의하여 간편하게 만들수있다~
모든 폼클래스는 django.forms.Form의 자식클래스로 생성
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=20)
각각의 폼 필드는 위젯 클래스를 갖고, 이는 <input type='text'>와 같은 HTML 폼 위젯으로 대응.
=> 각각의 폼 필드는 디폴트로 위젯 클래스 가짐
=> CharField: TextInput이 디폴트 위젯, 이를 textarea로 변경하려면 폼 필드 정의할 때 명시하면됨
your_name = forms.CharField(label = 'Your name', max_length=20, widget=forms.Textarea)
장고의 폼 클래스 => 모드너 필드에 유효성 검사 루틴 실행시키는 is_valid() 메소드를 가짐
=> 모든 필드가 유효하다면 True를 반환하고 cleaned_data 속성에 넣음
=> 위 코드에 대한 결과는
<label for="your_naem">Your name: </label>
<input id='your_name' type='text' name='your_name" maxlength='20'>
으로 나옴
-결과에 <form>태그나 submit은 없기 떄문에 개발자가 직접 템플릿에 넣어줘야함
=> 다음과 같이 html에서 템플릿 사용하기
<form action='/your-name/' method='post'>
{% csrf_token %}
{{ form }}
<input type='submit' value='Submit' />
</form>
=> form 변수는 뷰에서 컨텍스트 변수에 포함되어 템플릿 시스템으로 넘어감
*뷰에서 폼 클래스 처리
-앞에서 작성한 NameForm 폼 클래스와 템플릿을 사용하여 폼을 보여주고 폼 데이터를 수신하여 처리하는 뷰 작성
-폼을 처리하는 뷰는 2개 필요
=> 폼을 보여주는 뷰 + 제출된 폼을 처리하는 뷰, 장고에서는 통합하여 처리하는것을 권장(?)
==> 하나의 뷰에서 2가지 기능을 처리하기 위해서 처음 보여주는 폼과 입력 후 제출된 폼을 구분항려 처리
===> HTTP 메소드로 구분: GET 방식으로 요청받은 경우 처음 폼을 보여주고, POST 방식은 제출된 폼으로 간주
*폼 클래스를 템플릿으로 변환
-{{ form }} => label, input으로 렌더링됨
-{{ form.as_table }} => <tr>태그로 감싸서 테이블 셀로 렌더링
-{{ form.as_p }} => <p>태그로 감싸서 렌더링
-{{form as_ul }} => <li> 태그로 감싸도록 렌더링
5. 클래스형 뷰 (CBV)
1) 클래스형 뷰의 시작점
-가장 먼저 URLconf에서 함수형 뷰(views.xxx) 대신 클래스형 뷰(as_view())를 사용해야함
-장고의 URL 해석기는 리퀘스트 파라미터를 함수에 전달 => as_view() 클래스 메소드로 클래스로 진입: 진입 메소드
=> 클래스의 인스턴스생성, 인스턴스의 dispatch() 메소드 호출
==> dispatch(): 요청 검사, GET, POST등 어떤 HTTP 메소드로 요청됐는지 확인 후 해당 이름을 갖는 메소드로 요청 중계, 정의가 안되있으면 HttpResponseNotAllowed 익셉션
-그 이후 View 클래스 코딩(views.py)
from django.views.generic imprt View # View 클래스 안에 as_view, dispatch가 정의되어 있어서 정의하지 않아도 사용 가능
class MyView(view):
def get(self, request):
return HttpResponse('result')
2) 장점: 효율적인 메소드 구분
-HTTP 메소드에 따른 처리 기능 코딩시, IF 함수 없이 메소드명으로 구분 가능
-HTTP 메소드(GET, POST 등..)를 수신한 후 어떻게 처리하는지
함수형 뷰에서 GET 메소드 처리 로직:
def my_view(request):
if request.method == 'GET': #이렇게 if 문으로 GET 메소드인지를 확인해야함
>클래스형 뷰에서 GET 메소드 처리 로직:
class MyView(View):
def get(self, request): # 코드 구조가 훨씬 깔끔, 메소드명 소문자기 때문에 get, post 등...
=> 내부의 dispatch() 메소드가 어떤 HTTP 메소드인지를 알아내고 요청을 중계
3) 장점2: 상속 기능 가능
-이를 이해하려면 generic view를 알아야함: 뷰 개발 과정에서 공통으로 사용하는 기능을 추상화,
=> 이를 장고에서 미리 만들어 제공해주는 클래스형 뷰
# abtout.html 템플릿 보여주는 예제
# views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = 'about.html' # 오버라이딩하여 사용 가능
4) Generic view: 공통된 로직을 미리 개발해 놓고 제공하는 뷰
4가지 분류-
-Base View: 뷰 클래스 생성, 다른 generic view의 parents class 제공
=> View: 가장 기본이 되는 최상위 뷰
=> TemplateView: 템플릿이 주어지면 해당 템플릿 렌더링
=> RedirectView: URL이 주어지면 해당 URL로 리다이렉트
-Generic Display View: 객체의 리스트, 특정 객체의 디테일 보여줌
=> DetailView: 객체 하나에 대한 상세한 정보 보여줌
=> ListView: 조건에 맞는 여러 객체 보여줌
-Generic Edit View: 폼을 통해 객체를 생성, 수정, 삭제
=> FormView: 폼이 주어지면 해당 폼을 보여줌
=> CreateView: 객체를 생성하는 폼을 보여줌
=> UpdateView
=> DeleteView
-Generic Date View: 날짜 기반 객체의 년/월/일을 페이지로 구분
=> YearArchiveView
=> MonthArchiveView
=> DayArchiveView
### https://doce.djangoproject.com/1.10/ref/class-based-view/ 더 참고하기
5) 클래스형 뷰에서 폼처리: 함수형 뷰, View, FormVIew로 폼을 처리
FormView로 form 처리하는법
from django.views.generic.edit import FormView
class MyFormView(FormView):
form_class = MyForm # form.py 내의 클래스명
template_name = 'form_template.html' # 렌더링할 템플릿명
success_url = '/thanks/' # 리다이렉트 시킬 URL
def form_valid(self, form): # 유효한 폼 데이터로 처리할 로직: super() 호출해야함
return super(MyFormView, self).form_valid(form)
6. 로그 남기기: Logger, Handler, Filter, Formatter ==> 이게 무슨말인지? 더 공부해야할듯.. ㅠㅠ
1) Logger
-로깅 시스템의 시작점. 메세지를 담아두는 저장소
=> 로그 레벨: 메세지의 중요도에 따라서
-DEBUG: 디버그용도
-INFO: 일반적, 보편적 정보
-WARNING: 덜 중요한 문제 발생 시 이에대한 정보
-ERROR: 주요 문제 발생 시 이에 대한 정보
-CRITICAL: 치명적인 문제점
=> 저장되는 메세지: 로그 레코드
02202-486-1224255-41533
'backend > django' 카테고리의 다른 글
터미널이 꺼졌을 경우 장고 테스트 서버 끄는 법 (0) | 2017.03.13 |
---|---|
5장 실습 예제 확장 (0) | 2017.03.10 |
3장, 장고 웹 프레임워크: MTV(Moedl, Template, View) (0) | 2017.03.08 |
기본편 1장 웹프로그램의 이해, 2장 파이썬 웹 표준 라이브러리 (0) | 2017.03.08 |
실전편- Blog 앱 만들기 (0) | 2017.03.06 |