장고(DJango) 애플리케이션 만들기
- 리눅스 설치
- sudo pip3 install Django
- 업그레이드 : sudo pip3 install Django –upgrade
- 윈도우 설치
- pip install Django
- 업그레이드 : pip install Django –upgrade
- 윈도우 환경에서는 python3 대신 python을 사용
- 장고에서의 애플리케이션 개발 방식
- MVT 방식 : Model, View, Template (MVC; Model, View, Controller와 유사)
- 프로젝트 구조 만들기
- 프로젝트 생성 : mysite
- django-admin startproject mysite
- 다음과 같은 폴더와 파일이 생성됨
- 기본 테이블 생성 : manage.py가 있는 폴더에서 실행
- python3 manage.py migrate
- migrate 명령 : 데이터베이스에 변경사항이 있을 때 이를 반영하라는 명령
- db.sqlite3 파일이 생성됨
- 실행 : manage.py가 있는 폴더에서 실행
- python3 manage.py runserver 0.0.0.0:8000
- runserver : 테스트용 웹서버
- http://localhost:8000 또는 http://127.0.0.1:8000
- python3 manage.py runserver 0.0.0.0:8000
- 관리자 생성
123456whan@MoakLinux:~/django/mysite$ python3 manage.py createsuperuserUsername (leave blank to use 'whan'): whanEmail address: whan0623@gmail.comPassword:Password (again):Superuser created successfully. - http://localhost:8000/admin : 관리자 접속
- 프로젝트 생성 : mysite
- 프로젝트 설정 파일 : mysite/settings.py
- 개발모드와 운영모드 선택
- DEBUG = True : 개발모드
- DEBUG = False : 운영모드 <–완성한 후에는 운영모드로 변경
- ALLOWED_HOSTS = []
- 개발모드일 경우 : 127.0.0.1이 등록된것으로 인식
- http://localhost:8000로 접속
- 운영모드일 경우 : 서버의 IP주소를 반드시 써줘야 함
- ALLOWED_HOSTS = [‘127.0.0.1’, ‘localhost’, ‘202.31.243.99’, ‘ora.jj.ac.kr’]
- http://ora.jj.ac.kr:8000로 접속
- ALLOWED_HOSTS에 202.31.243.99만 등록하고 ora.jj.ac.kr을 등록하지 않았다면 http://ora.jj.ac.kr:8000로 접속하면 오류 발생
- 개발모드일 경우 : 127.0.0.1이 등록된것으로 인식
- INSTALLED_APPS : 프로젝트에 등록된 모든 애플리케이션
12345678INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',] - 데이터베이스 엔진
- 기본 SQLite3 데이터베이스 엔진 사용
123456DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}} - 다른 DB 사용하려면 여기서 변경
- 기본 SQLite3 데이터베이스 엔진 사용
- 타임존 지정 : ‘Asiz/Seoul’ 로 변경
12# TIME_ZONE = 'UTC'TIME_ZONE = 'Asia/Seoul'
- 개발모드와 운영모드 선택
- 애플리케이션 생성 : growth
- cd mysite
- python3 manage.py startapp growth
- 프로젝트에 polls 애플리케이션을 등록 : mysite/settings.py
123456789INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','growth.apps.GrowthConfig',]- growth.apps.GrowthConfig: growth폴더의 apps.py의 GrowthConfig클래스를 등록하라는 의미
- Model 코딩
- 테이블 정의 : models.py에 class 생성 -> DB에 table이 생성됨
- vi ./growth/models.py
1234567891011121314151617from django.db import models# Create your models here.class Growth(models.Model):cham_id = models.CharField(max_length=20)height = models.FloatField()branch = models.IntegerField()degree = models.FloatField()humidity = models.FloatField()state = models.TextField()wdate = models.DateTimeField()cdate = models.DateTimeField()pic = models.CharField(max_length=200)def __str__(self):return self.cham_id
- vi ./growth/models.py
- Admin 사이트에 테이블 반영
- vi ./growth/admin.py
1234567from django.contrib import admin# Register your models here.from growth.models import Growthadmin.site.register(Growth)
- vi ./growth/admin.py
- 데이터베이스 변경사항 반영 : DB Browser for Sqlite 프로그램으로 저장 내용 확인
- python3 manage.py makemigrations
- python3 manage.py migrate
- 작업 결과 확인
- http://ora.jj.ac.kr:8000/admin : 관리자 접속
- View와 Template 코딩
- 처리 흐름 설계
- URL View Template
- /polls/ index() index.html
- /polls/5/ detail() detail.html
- /polls/5/vote/ vote() -> redirect
- /polls/5/results/ results() results.html
- URLconf 설계 – URL과 뷰 매핑
- URL 패턴 View 이름 View가 처리하는 내용
- /polls/ index() index.html 템플릿을 보여줌
- /polls/5/ detail() detail.html 템플릿을 보여줌
- /polls/5/vote/ vote() detail.html의 폼을 POST 방식으로 처리
- /polls/5/results/ results() results.html 템플릿을 보여줌
- /admin/ (장고 기능) Admin 사이트를 보여줌
- 템플릿 작성 1 : 템플릿으로 index.html 파일을 생성 / views.py에 index() 함수 추가 / urls.py에 path() 추가
- mkdir ./growth/templates
- mkdir ./growth/templates/growth
- vi ./growth/templates/growth/index.html
123456789{% if latest_growth_list %}<ul>{% for growth in latest_growth_list %}<li>{{ growth.id }} {{ growth.cham_id }} {{ growth.height }}</li>{% endfor %}</ul>{% else %}<p>No growth are available.</p>{% endif %} - vi ./growth/views.py
12345678910from django.shortcuts import render, get_object_or_404# Create your views here.from growth.models import Growthdef index(request):latest_growth_list = Growth.objects.all().order_by('-wdate')[:5]context = {'latest_growth_list': latest_growth_list}return render(request, 'growth/index.html', context)- def index(request) : 뷰 함수 index()를 정의
- latest_question_list : 템플릿에게 넘겨줄 객체 이름
- Question 테이블에서 pub_date의 역순으로 최근 5개
- context : 템플릿에 넘겨주는 방식으로 이를 render()함수에게 보내줌
- render() : 장고의 단축함수로 context 변수를 적용하여 polls/index.html을 만들고 이를 HttpResponse객체로 반환
- 단축함수(shortcut function) : 공통적으로 사용되는 기능들을 장고에서 미리 개발하여 내장함수로 제공하는 함수
- vi ./growth/urls.py
1234567from django.urls import pathfrom growth import viewsapp_name='growth'urlpatterns = [path('', views.index, name='index'),] - vi ./mysite/urls.py
1234567from django.contrib import adminfrom django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('growth/', include('growth.urls')),] - ./growth/urls.py를 생성하지 않고 ./mysite/urls.py 1개로 운영할수도 있음
- 결과 확인
- ……………..
- ……………..
- 템플릿 작성 2 : 템플릿으로 detail.html 파일을 생성 / views.py에 detail() 함수 추가 / urls.py에 path() 추가
- vi ./polls/templates/polls/detail.html
123456789101112<h1>{{ question.question_text }}</h1>{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}<form action="{% url 'polls:vote' question.id %}" method="post">{% csrf_token %}{% for choice in question.choice_set.all %}<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /><label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />{% endfor %}<input type="submit" value="Vote"/></form>- error_message : polls/views.py에 vote() 함수의 try~except에서 정의한 변수로, 에러 발생시 발생한 에러가 저장됨
- post : 서버 측의 데이터를 변경하는 경우 일반적으로 GET이 아니라 POST 방식을 사용
- csrf token : 폼을 처리하는 경우 보안 측면에서 CSRF(Cross Site Request Forgery) 공격을 방지하기 위해 제공된 기능
- forloop.counter : for loop를 실행한 횟수를 담는 변수
- vi ./polls/views.py
1234567891011121314from django.shortcuts import render, get_object_or_404# Create your views here.from polls.models import Choice, Questiondef index(request):latest_question_list = Question.objects.all().order_by('-pub_date')[:5]context = {'latest_question_list': latest_question_list}return render(request, 'polls/index.html', context)def detail(request, question_id):question = get_object_or_404(Question, pk=question_id)return render(request, 'polls/detail.html', {'question': question})- get_object_or_404() : 모델 클래스로부터 검색 조건에 맞는 객체 조회하는 단축함수
- 매개변수1 : 모델 클래스
- 매개변수2… : 검색 조건을 여러개 사용
- 조건에 맞는 객체가 없으면 Http404 익셉션 발생
- get_list_or_404() : filter() 함수 사용, 리스트가 비어 있으면 Http404 익셉션 발생하는 단축함수
- get_object_or_404() : 모델 클래스로부터 검색 조건에 맞는 객체 조회하는 단축함수
- vi ./polls/urls.py
12345678from django.urls import pathfrom polls import viewsapp_name='polls'urlpatterns = [path('', views.index, name='index'),path('<int:question_id>/', views.detail, name='detail'),] - 실행결과
- vi ./polls/templates/polls/detail.html
- 템플릿 작성 3 : 템플릿으로 results.html 파일을 생성 / views.py에 vote(), results() 함수 추가 / urls.py에 path() 추가
- vi ./polls/templates/polls/results.html
123456789<h1>{{ question.question_text }}</h1><ul>{% for choice in question.choice_set.all %}<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>{% endfor %}</ul><a href="{% url 'polls:detail' question.id %}">Vote again?</a> - vi ./polls/views.py
12345678910111213141516171819202122232425262728293031323334from django.shortcuts import render, get_object_or_404# Create your views here.from django.http import HttpResponseRedirectfrom django.urls import reversefrom polls.models import Choice, Questiondef index(request):latest_question_list = Question.objects.all().order_by('-pub_date')[:5]context = {'latest_question_list': latest_question_list}return render(request, 'polls/index.html', context)def detail(request, question_id):question = get_object_or_404(Question, pk=question_id)return render(request, 'polls/detail.html', {'question': question})def results(request, question_id):question = get_object_or_404(Question, pk=question_id)return render(request, 'polls/results.html', {'question': question})def vote(request, question_id):question = get_object_or_404(Question, pk=question_id)try:selected_choice = question.choice_set.get(pk=request.POST['choice'])except(KeyError, Choice.DoesNotExist):return render(request, 'polls/detail.html', {'question': question,'error_message': "You didn't select a choice.",})else:selected_choice.votes += 1selected_choice.save()return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))- KeyError : POST 데이터에 choice키가 없으면 KeyError 익셉션 발생
- Choice.DoesNotExist : 검색 조건에 맞는 객체가 없으면 Choice.DoesNotExist 익셉션 발생
- vi ./polls/urls.py
12345678910from django.urls import pathfrom polls import viewsapp_name='polls'urlpatterns = [path('', views.index, name='index'),path('<int:question_id>/', views.detail, name='detail'),path('<int:question_id>/results/', views.results, name='results'),path('<int:question_id>/vote/', views.vote, name='vote'),] - 실행결과
- vi ./polls/templates/polls/results.html
- 처리 흐름 설계
- 테이블 정의 : models.py에 class 생성 -> DB에 table이 생성됨